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

问题描述 投票:1回答:2

试图调用多个异步函数,并由此获得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.
    }
  });

如何等待异步功能?

javascript node.js ecmascript-6 ecmascript-5 ecmascript-2017
2个回答
2
投票

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

你有几个选择:

  1. 以递归方式调用mongoDB - 将此查询包装在查询返回后调用自身的函数中。
  2. 阅读有关mongoDB批处理操作的信息 - https://docs.mongodb.com/manual/reference/method/Bulk/
  3. 通过将异步瀑布中的回调函数声明为“async”,然后在函数内部为每个查询使用“await”,对每个调用使用async / await模式。开箱即用,forEach不是异步。如果你仍想使用forEach,你可以重新编写async(见下文)或使用常规for循环:

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

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


2
投票

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

你是对的,异步性质现在让你变得困难,但假设你使用了Promise并将它们链接在一起,这将为你节省很多麻烦。

曾经有一次我有类似的异步代码运行故障的问题我想要,所以我使用自定义承诺函数做了一点Tweak(我mead up)并称之为订单..如果你能应用它,想法可以解决你的问题你的代码正确https://github.com/lalosh/Ideas/blob/master/promiseOrder.js

© www.soinside.com 2019 - 2024. All rights reserved.