**遍历数组**
* * * * *
在遍历数组时,使用某个函数依次对数据成员做一些处理也是常见的需求。如果函数是同步执行的,一般就会写出以下代码:
![](https://box.kancloud.cn/f9083394e3658fabab14e4ad3c04f440_320x340.png)
```
for (let i = 0, len = arr.length; i < len; i++) {
arr[i] = sync(arr[i])
}
```
`For`循环语句3,`i++` 和 `++i` 区别不大。
这里我们主要讨论如何在异步函数内遍历数组,如果函数是异步执行的,以上代码就无法保证循环结束后所有数组成员都处理完毕了。如果数组成员必须一个接一个串行处理,则一般按照以下方式编写异步代码:
```
let result = []
let arr = [1, 2, 3, 4, 5, 6, 7]
// 自定义异步函数, 为了简单说明问题
// 这里简单的调用回调函数即可
// 实际开发根据项目需求改动
function async(item, fn) {
setTimeout(function () {
fn(item)
}, 1000)
}
// ()前面最好加个操作符, 避免报错
~(function next(i, len, callback) {
if (i < len) {
// 调用异步API, 串行处理, 最后执行callback
async(arr[i], function (value) {
console.log(i)
result[i] = value
next(i + 1, len, callback)
})
} else {
// 保证所有数组元素都处理完毕
// 最后调用回调函数
callback(result)
}
})(0, arr.length, function (result) {
// 回调函数处理结果result
console.log(result)
})
console.log('开始next函数')
```
![](https://box.kancloud.cn/b2e225dd8567eb10d94ef6e93a4057ea_553x214.png)
可以看到,以上代码在异步函数执行一次并返回执行结果后才传入下一个数组成员并开始下一轮执行,直到所有数组成员处理完毕后,通过回调的方式触发后续代码的执行。
* * * * *
如果想要数组成员可以并行处理,但后续代码仍然需要所有数组成员处理完毕后才能执行的话,则异步代码会调整成以下形式:
```
let result = []
let arr = [1, 2, 3, 4, 5, 6, 7]
// 自定义异步函数, 为了简单说明问题
// 这里简单的调用回调函数即可
// 实际开发根据项目需求改动
function async(item, fn) {
setTimeout(function () {
fn(item)
}, 1000)
}
// ()前面最好加个操作符, 避免报错
~(function (i, len, count, callback) {
// 并行版本进来先创建并发执行的闭包
// 每个闭包内都有一个回调函数, 去判断数组元素是否全部处理完毕
for (; i < len; i++) {
(function (n) {
async(arr[n], function (value) {
console.log(n)
result[n] = value
// 此时元素已经处理了
// 所以count必须先自加, 再对比值
if (++count === len) callback()
})
})(i)
}
})(0, arr.length, 0, function () {
console.log(result)
})
console.log('开始next函数')
```
![](https://box.kancloud.cn/0b379d75052c77026ba59ebe5c0de490_565x211.png)
可以看到,与异步串行遍历的版本相比,以上代码并行处理所有数组成员,并通过计数器变量来判断什么时候所有数组成员都处理完毕了,代码中的索引基本是同时执行的,即证明了该异步函数是并行处理的。