在退出循环之前,如何等待循环内的异步进程完成?

时间:2016-09-22 21:14:16

标签: javascript node.js mongodb loops asynchronous

我在JavaScript forEach循环中运行了一些异步代码。我想等到异步进程内的代码完成运行后才继续循环。

以下示例:

ids是一个字符串数组。 db是我创建的用于处理MongoDB的节点模块

var appIdsNotFound = "";
var count = 0;
ids.forEach(function(id) {
    output[count] = {};
    //console.log(id);
    db.findApp(id, function(error, result) {
        if(error) {
            fatalError = true;
            console.log(error);
        } else {
            if (result) {
                output[count] = result;
                //console.log(output[count]);
                count++;
            } else {
                appNotFound = true;
                appIdsNotFound += id + ", ";
                console.log(appIdsNotFound);
            }
        }
    });
});

//more code that we want to wait before executing

有没有办法在执行循环外的其余代码之前等待,如果是这样,我将如何去做。

2 个答案:

答案 0 :(得分:1)

  1. 假设db是访问数据库的某个模块,请尝试查找同步版本。这假设您可以使用同步,因为您尝试以这种方式编写它,等待所有事情再继续。

  2. 如果您的数据库库使用promises,则可以将其与Promise.all结合使用。触发每个项目的请求,收集数组中的所有承诺,将其提供给Promise.all。所有承诺解决后,Promise.all的承诺将得到解决。

    const promises = ids.map(id => db.promiseReturningFindApp(id));
    const allRequests = Promise.all(promises).then(responses => {
      // responses is an array of all results
    });
    
  3. 如果您没有承诺返还API的版本,请将db.findApp包含在承诺中,请执行建议#2。

    function promiseReturningFindApp(id){
      return new Promise((resolve, reject) => {
        db.findApp(id, (error, result) => {
          if(error) reject(error);
          else resolve(result);
        });
      });
    }
    
  4. 选项2和3是异步的,因此,您在技术上不会等待"。因此,需要执行的代码只能驻留在回调中。

答案 1 :(得分:0)

您可以将每个项目都放入一个函数中并使用async

var async = require('async');

var output = [], appsNotFound = [];
var appRequests = ids.map((id) => (cb) => {
    db.findApp(id, (error, result) => {
        if (error) {
            appsNotFound.push(id);
            return cb();
        }
        output.push(id);
        return cb();    
    })
})

async.parallel(appRequests, () => {
    console.log('N# of Apps found',output.length);
    console.log("Ids not found:",appIdsNotFound.join(','))
    console.log("N# Apps not found:",appIdsNotFound.length)
})

如果数据库无法处理,请尝试使用async.serial

如果您愿意,可以使用promises创建类似的东西,但这需要更少的代码行。

相关问题