**遍歷數組**
* * * * *
在遍歷數組時,使用某個函數依次對數據成員做一些處理也是常見的需求。如果函數是同步執行的,一般就會寫出以下代碼:

```
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函數')
```

可以看到,以上代碼在異步函數執行一次并返回執行結果后才傳入下一個數組成員并開始下一輪執行,直到所有數組成員處理完畢后,通過回調的方式觸發后續代碼的執行。
* * * * *
如果想要數組成員可以并行處理,但后續代碼仍然需要所有數組成員處理完畢后才能執行的話,則異步代碼會調整成以下形式:
```
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函數')
```

可以看到,與異步串行遍歷的版本相比,以上代碼并行處理所有數組成員,并通過計數器變量來判斷什么時候所有數組成員都處理完畢了,代碼中的索引基本是同時執行的,即證明了該異步函數是并行處理的。