話很少少,進入正文。bash
首先來看這兩道題:異步
// 定義一個fetch函數模擬異步請求
function fetch(x) {
return new Promise((resolve, reject) => {
console.log('aaa');
setTimeout(() => {
resolve(x)
}, 500 * x)
})
}
// 第一題:
function test() {
let arr = [3, 2, 1]
arr.forEach(async item => {
const res = await fetch(item)
console.log(res)
})
console.log('end')
}
test();
輸出結果:3次aaa , end ,1 , 2 , 3
// 第二題:
async function test() {
let arr = [3, 2, 1]
for (const item of arr) {
const res = await fetch(item)
console.log(res)
}
console.log('end')
}
test();
輸出結果:aaa , 3 , aaa , 2 , aaa , 1 , end
複製代碼
爲何一樣是遍歷,輸出結果卻不同呢?async
由於 for...of 內部處理的機制和 forEach 不一樣,forEach 是直接調用回調函數,for...of 是經過迭代器的方式去遍歷。函數
二者的處理機制:fetch
while (index < arr.length) {
// 也就是咱們傳入的回調函數
callback(item, index)
}
複製代碼
async function test() {
let arr = [3, 2, 1]
const iterator = arr[Symbol.iterator]() //for of會自動調用遍歷器函數
let res = iterator.next()
while (!res.done) {
const value = res.value
const res1 = await fetch(value)
console.log(res1)
res = iterator.next()
}
console.log('end')
}
複製代碼
可能有的讀者會對aaa的輸出位置有疑問,本文異步請求中涉及setTimeout,所以牽扯到JS引擎的執行機制(宏任務和微任務)。故在此很少加贅述了。ui