學習JavaScript循環下的async/await

問題描述

在進行業務開發的過程當中,使用了數組的高級函數map,同時使用了ES6語法async/await,發如今map循環下任務是異步執行的,並不符合預期html

例子說明

/**
 * 異步打印數據
 */
const echo = async (i) => {
    return new Promise((resolve,reject)=>{
        setTimeout(() => {
            console.log('i===>', i,new Date().toLocaleTimeString());
            resolve(i) ;
        }, 100);
    })

}
/**
 * 模擬異步任務
 */
const task = async () => {
    dataArr.forEach( async( item, i ) => {
        await echo(i);
    })
}
/**
 * 啓動函數入口
 */
const run = async () => {
    console.log('run-start====>date:', new Date().toLocaleDateString())
    await task() ;
    console.log('run-end======>date:', new Date().toLocaleDateString())
}
/**
* 啓動函數
*/
(async () => {
    console.log('start...')
    await run();
    console.log('end...')
})()

//預期效果
start...
run-start====>date: 2019-2-16
i===> 0 23:19:04
i===> 1 23:19:04
i===> 2 23:19:04
i===> 3 23:19:04
run-end======>date: 2019-2-16
end...

//打印結果
start...
run-start====>date: 2019-2-16
run-end======>date: 2019-2-16
end...
i===> 0 23:19:04
i===> 1 23:19:04
i===> 2 23:19:04
i===> 3 23:19:04

從上面的例子能夠看出,在map循環下使用await後, 函數結束標誌信號run-end先於異步任務數據i輸出,故task任務仍然是異步執行,並不符合預期。緣由是Array的循環方法map、forEach、filter、reduce、some、every等是並行迭代,能夠理解爲async/await的效果是無效的數組

解決方案

  • 使用最原始的for循環
  • for...of

將上述的模擬異步任務修改成異步

for (var i = 0; i < dataArr.length; i++) {
     await echo(i)
 }
 或
 for (const i of dataArr) {
     await echo(i)
 }

參考鏈接

用 async/await 來處理異步
await在forEach不起做用解決
JavaScript 異步循環 - async/await 的使用方法
相關文章
相關標籤/搜索