如何在 Array.forEach 中正確使用 Async


header

本文譯自How to use async functions with Array.forEach in Javascript - Tamás Sallai

0. 如何異步遍歷元素

第一篇文章中,我們介紹了async / await如何幫助處理異步事件,但在異步處理集合時卻無濟於事。在本文中,我們將研究該forEach功能,當您需要為集合中的每個元素運行一段代碼時,該功能將非常有用。

1. forEach

forEach函數類似於map,但是它不轉換值並使用結果,而是為每個元素運行該函數並丟棄結果(這里可以理解成是否有return值)。實際上,重要的部分是調用函數的副作用。

例如,將每個元素同步打印到控制台:

const arr = [1, 2, 3];

arr.forEach((i) => {
	console.log(i);
});

// 1
// 2
// 3

console.log("Finished sync");
// Finished sync

由於結果並不重要,因此可以使用異步函數作為迭代器:

const arr = [1, 2, 3];

arr.forEach(async (i) => {
	// each element takes a different amount of time to complete
	await sleep(10 - i);
	console.log(i);
});

console.log("Finished async");
// Finished async

// 3
// 2
// 1

forEach

2. 控制時間

2.1 等待完成

但是,並不奇怪,該函數被異步調用,並且程序執行超出了調用范圍。這是與同步版本的重要區別,因為在執行下一行時,同步forEach已經完成,而異步版本尚未完成。這就是為什么“完成的異步”日志出現在元素之前的原因。

要在繼續進行之前等待所有函數調用完成,可以使用帶有Promise.allmap,並丟棄結果:

const arr = [1, 2, 3];

await Promise.all(arr.map(async (i) => {
	await sleep(10 - i);
	console.log(i);
}));

// 3
// 2
// 1

console.log("Finished async");
// Finished async

map

進行此更改后,“完成的異步操作”排在最后。

2.2 順序處理

但是請注意,迭代函數是並行調用的。要忠實地遵循同步forEach,要先使用帶await memoreduce

const arr = [1, 2, 3];

await arr.reduce(async (memo, i) => {
	await memo;
	await sleep(10 - i);
	console.log(i);
}, undefined);

// 1
// 2
// 3

console.log("Finished async");
// Finished async

reduce

這樣,元素依次依次處理,程序執行將等待整個數組完成后再繼續。

3. 結論

異步forEach易於使用,但是是否應使用forEachmapreduce取決於計時的要求。如果您只想在任何時候運行這些功能,請使用forEach。如果要確保繼續操作之前完成操作,請使用map。最后,如果您需要一個一個地運行它們,請使用reduce

wx


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM