迴圈中的 async/await

結論

  • forEach、map、reduce 之類有一個callbackFn的都不會等待
  • 其他 loop 都會等待

更追根究底一點應該要去研究,map、reduce 之類的 function,javascript engine 是怎麼實現的, 不過實務上還是用 Promise.all()、Promise.allSettled()之類的去處理比較好

驗證

forEach

const ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ids.forEach(async (id) => {
    await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
})

forEach 的 network waterfall 圖 foreach

  • 而且因為每次請求所花的時間會稍微不一樣,所以完成的順序也可能不固定

map

const ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ids.map(async (id) => {
    const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
})

map 的 network waterfall 圖 foreach

  • 行為跟 forEach 一樣

reduce

const ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ids.reduce(async (acc, id) => {
    const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
}, [])

reduce 的 network waterfall 圖 foreach

  • 行為跟 forEach 一樣

for ... of

const ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const fetchData = async () => {
    for (const id of ids) {
        await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
    }
}
fetchData()

for of 的 network waterfall 圖 foreach

  • 他會等前面一個執行完,才會執行下一個

for loop

const ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const fetchData = async () => {
    for (let i = 0; i < ids.length; i++) {
        await fetch(`https://jsonplaceholder.typicode.com/posts/${ids[i]}`)
    }
}
fetchData()

for loop 的 network waterfall 圖 foreach

  • 跟 for in 一樣,他會等前面一個執行完,才會執行下一個

while loop

const ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const fetchData = async () => {
    let x = 0
    while (x < ids.length) {
        await fetch(`https://jsonplaceholder.typicode.com/posts/${ids[x]}`)
        x++
    }
}
fetchData()

while loop 的 network waterfall 圖 foreach