如何等待来自 forEach 循环的多个异步调用?

Posted

技术标签:

【中文标题】如何等待来自 forEach 循环的多个异步调用?【英文标题】:How to wait for multiple asynchronous calls from forEach loop? 【发布时间】:2019-02-18 13:02:09 【问题描述】:

尝试调用多个异步函数,导致结果为undefined

尝试async.waterfall,但无法使其工作。

代码:

const pendingData = [];

async.waterfall([
    function (callback) 
      WaitForApproval.find(, (err,result) => 
        callback(null,result);
      );
    ,
    function (result, callback) 
      result.forEach(data => 
        User.findOne(_id: data.uploadedBy, (err,name) => 
          let total = 
            id: data._id,
            name: name.name,
            subject: data.subject,
            uploadOn: data.uploadedAt
          ;
          pendingData.push(total);
        );
      );
      callback(null,'done');
    
  ], function (err,result) 
    if(result === 'done')    
      console.log(pendingData); // it is giving empty result.
    
  );

如何等待异步函数?

【问题讨论】:

只需将result.forEach 更改为async.seriesasync.parallel How to wait for multiple asynchronous calls from for loop?的可能重复 【参考方案1】:

您遇到的问题是您是非异步 forEach 循环中的异步函数。

你有几个选择:

    递归调用 mongoDB - 将此查询包装在一个函数中,该函数在查询返回后调用自身。

    了解 mongoDB 批处理操作 - https://docs.mongodb.com/manual/reference/method/Bulk/

    通过将异步瀑布中的回调函数声明为“异步”,然后在每个查询的函数内部使用“等待”,对每次调用使用异步/等待模式。开箱即用,forEach 不是异步的。如果您仍想使用 forEach,您可以异步重写它(见下文)或使用常规 for 循环:

async function asyncForEach(array, callback) 
  for (let index = 0; index < array.length; index++) 
    await callback(array[index], index, array)
  

** 除了此处发布的内容之外,还有其他方法可以解决此问题,但如果实施正确,这里有一些方法将起作用。

【讨论】:

这将在第一个 User.findOne 完成后触发回调。那还为时过早。也许你可以测试pendingData的长度:if (pendingData.length === result.length) callback(null, pendingData) 当我使用 forEach 时出现错误,callback 将在循环外使用。 @MarkMeyer 你是对的!我没有意识到这里有一个 forEach 被调用——我很抱歉;我很快对此做出了回应,因为我刚刚在工作中处理了同样的问题:) @MarkMeyer,这个技巧奏效了。但肯定还有其他方法可以解决这个问题。【参考方案2】:

我建议您立即添加对callback(null,'done'); 的调用pendingData.push(total);

你是对的,异步特性现在让你很难过,但假设你使用 Promise 并将它们链接在一起,那会为你省去很多麻烦。

有一次我遇到了类似的异步代码乱序问题,所以我使用自定义的 promise 函数(我猜到了)做了一点调整,并称之为 order..这样的想法可以解决你的问题,如果你可以正确地将其应用于您的代码 https://github.com/lalosh/Ideas/blob/master/promiseOrder.js

【讨论】:

你的 sn-p 很棒,但我认为有几件事可以改进它: - 删除控制台日志整数,它们是无关的 - 如果你使用 async/await 架构和 promisified 函数,你可以避免 .then() 回调

以上是关于如何等待来自 forEach 循环的多个异步调用?的主要内容,如果未能解决你的问题,请参考以下文章

ForEach 循环中的异步/等待节点 Postgres 查询

在 forEach 循环中等待 promise

如何正确调用 Parallel.ForEach 循环中的调用异步方法[重复]

node.js:如何在 forEach 循环中使用异步调用实现路由方法?

执行异步forEach循环后重新定义全局变量[重复]

C# 在 foreach 循环中发出异步 http 请求