Nodejs中如何等待 foreach 完成之后才能进行下一步?

发布于 1周前 作者 caililin 来自 nodejs/Nestjs

Nodejs中如何等待 foreach 完成之后才能进行下一步?
foreach 是异步,但在下一步之前,需要得到 foreach 的完成数据。应该如何处理?

25 回复

for of + async await ?


foreach 我记得是同步的

foreach 是异步是啥意思?

重新定义 foreach👍

写 java 的,不过题主的意思我明白了,foreach 中循环的方法体中调用了异步方法,而你又需要在后面的代码中使用 foreach 循环体中生成的数据,对标 java 中的 Future,可以搜一下 js 中怎么实现的

别用 foreach,用 map+Promise.all

php 吗? js 用 promise 的话可以这样:
js<br>let queue = Promise.resolve()<br>arr.forEach(e =&gt; {<br> queue = queue.then(() =&gt; someAsyncFunc(e))<br>})<br>

当然 async/await 也可以
js<br>async (function() {<br> arr.forEach(e =&gt; {<br> await someAsyncFunc(e)<br> })<br>})()<br>

for 循环不是同步的吗???

楼主的意思是 foreach 传进的那个函数是异步的…

用 bluebird.each 或者 p-each-series 这样的库

<br>const arr = [1, 2, 3];<br>const promises = [];<br>arr.forEach(v =&gt; {<br> promises.push(Promise.resolve(v));<br>});<br>Promise.all(promises).then(result =&gt; {<br> console.log(result); // [1,2,3]<br>});<br>

foreach 是同步的好吗?

  1. 继发: Loop await 即可
    2. 继发 Iterator: for await of 即可
    3. 并发: Promise.all([].map(async item => await todo(item))) 是比较简单的方式
    4. 并发但忽略 reject 直到所有异步都完成: 3 改成 Promise.allSettled 。其他的并发但状态需求不同可参考其他 Promise 静态方法

    8 楼的例子还有其他几楼由明显错误,await 只能在 async 下,即便 forEach 了 async,在可读性上也是误以为继发的并发任务,有阅读歧义。此外 forEach 是典型的副作用的函数。

多提了下。
最新的 v8 已经支持 top await 了,不用限制 await 在 async 了。

目前 deno 、chrome 80 、firefox 72 已支持 top await.
````
export default config = await Promise.resolve({env:‘dev’})
```

async fun(){for(…){await …}}
每次循环请求一个接口,成功 /失败后才执行下一次循环

for…await…of 或者 Promsie.all(),异步并发问题一般需要计数器作为哨兵变量。

foreach 是同步的

你这个是不是有问题的呢?在 foreach 的匿名函数中 await 应该是不可以的吧。作用域变动了,用 for 就可以 await

是的,,写了个不负责任的回答,惭愧,谢谢指出。
自己试了一下,即使 async 放在 forEach 的匿名函数前也没用,会并行执行,查了一下这好像是个常见的误区。
http://objcer.com/2017/10/12/async-await-with-forEach/
https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop

const a = await Promise.all(array.map(async element => {
return await asyncFunction();
});

指出一点:forEach 的回调不能直接套 async/await
其他的方式都没问题,比如 promise.all

foreach 就是同步得啊,你的意思是不是在 foreach 里面异步调用?
有两种解决方案,一个是 Promise all,配合 async await,最新版本的 node 应该支持了
如果是老版本的 node,有一个库 http://caolan.github.io/async/v3/, 应该可以解决你的问题

在Node.js中,由于forEach方法是同步且非阻塞的,直接在其中等待所有异步操作完成并不直观。通常,我们会使用Promiseasync/await结合for...of循环来实现这一需求。以下是一个使用Promise.allasync/await的示例,展示了如何等待forEach中的所有异步操作完成后再进行下一步:

const asyncOperation = (item) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(`Processed ${item}`);
      resolve(item);
    }, 1000);
  });
};

const array = [1, 2, 3, 4, 5];

const processArray = async () => {
  const promises = array.map(async (item) => {
    return await asyncOperation(item);
  });

  const results = await Promise.all(promises);
  console.log('All operations completed:', results);
  // 进行下一步操作
  console.log('Next step...');
};

processArray();

在这个示例中,asyncOperation模拟了一个异步操作,例如数据库查询或网络请求。processArray函数通过map方法将数组中的每个元素转换为一个Promise,然后使用Promise.all等待所有Promise完成。最后,在所有异步操作完成后,打印结果并进行下一步操作。

这种方法确保了所有异步操作在继续执行后续代码之前都已经完成。使用for...of循环和Promise.all或直接在async函数中使用await是实现这一目标的常用方式。

回到顶部