本文译自:
How to use async functions with Array.forEach in Javascript - Tamás Sallai
。需要稳定的网络环境
如何异步遍历元素
在
第一篇文章中
,我们介绍了async / await如何帮助处理异步事件,但在异步处理集合时却无济于事。在本文中,我们将研究该
forEach
功能,当您需要为集合中的每个元素运行一段代码时,该功能将非常有用。
1.
forEach
该
forEach
函数类似于
map
,但是它不转换值并使用结果,而是为每个元素运行该函数并丢弃结果(这里可以理解成是否有
return
值)。实际上,重要的部分是调用函数的副作用。
例如,将每个元素同步打印到控制台:
const arr = [1 , 2 , 3 ];
arr.forEach ((i ) => {
console .log (i);
console .log ("Finished sync" );
由于结果并不重要,因此可以使用异步函数作为迭代器:
const arr = [1 , 2 , 3 ];
arr.forEach (async (i) => {
await sleep (10 - i);
console .log (i);
console .log ("Finished async" );
Async forEach image
2. 控制时间
2.1 等待完成
但是,并不奇怪,该函数被异步 调用,并且程序执行超出了调用范围。这是与同步版本的重要区别,因为在执行下一行时,同步forEach已经完成,而异步版本尚未完成。这就是为什么“完成的异步”日志出现在元素之前的原因。
要在继续进行之前等待所有函数调用完成,可以使用带有Promise.all的map,并丢弃结果:
const arr = [1 , 2 , 3 ];
await Promise .all (arr.map (async (i) => {
await sleep (10 - i);
console .log (i);
console .log ("Finished async" );
Async map image
进行此更改后,“完成的异步操作”排在最后。
2.2 顺序处理
但是请注意,迭代函数是并行调用的。要忠实地遵循同步forEach,要先使用带await memo的reduce:
const arr = [1 , 2 , 3 ];
await arr.reduce (async (memo, i) => {
await memo;
await sleep (10 - i);
console .log (i);
}, undefined );
console .log ("Finished async" );
Async reduce image
这样,元素依次依次处理,程序执行将等待整个数组完成后再继续。
3. 结论
异步forEach易于使用,但是是否应使用forEach,map或 reduce取决于计时的要求。如果您只想在任何时候运行这些功能,请使用forEach。如果要确保继续操作之前完成操作,请使用map。最后,如果您需要一个一个地运行它们,请使用reduce。
推荐阅读:
如何在 Vue 中优雅的使用防抖节流