如何在Node JS中等待多个回调

时间:2019-03-11 22:14:31

标签: javascript node.js asynchronous callback

我正在尝试等待多个回调,但我想不出一种很好的方法。

我的代码是:

module.exports.getFilledOnlineFormsOfArray = (formIDs, callback) => {
let forms = [];
for (let i = 0; i < formIDs.length; i++) {
    this.getFilledOnlineFormByID(formIDs[i], (err, filledForm) => {
        if (err) callback(err);
        else forms.push(filledForm);
    });
}
callback(null, forms);
};

只有解决了callback(null, forms)(IE getFilledOnlineFormByID)的每个回调之后,才如何调用(err, filledForm)

我想出了一种写作解决方案:

module.exports.getFilledOnlineFormsOfArray = (formIDs, callback) => {
    let forms = [];
    let count = formIDs.length;
    for (let i = 0; i < formIDs.length; i++) {
        this.getFilledOnlineFormByID(formIDs[i], (err, filledForm) => {
            if (err) callback(err);
            else forms.push(filledForm);
            count--;
            if (count === 0)
                callback(null, forms);
        });
    }
};

但是用这种方式编写代码感觉很糟糕。我敢肯定,对于这个问题有更好的解决方案。 我在互联网上寻找答案,但发现的只是如何将其转换为异步功能,而现在我无法在我的项目中做到这一点。

编辑: 我试图像这样使用Promise.all

module.exports.getFilledOnlineFormsOfArray = (formIDs, callback) => {
    let forms = [];
    let async = [];
    for (let i = 0; i < formIDs.length; i++) {
        async.push(this.getFilledOnlineFormByID(formIDs[i], (err, filledForm) => {
        if (err) callback(err);
        else forms.push(filledForm);
       }));
    }
    Promise.all(async).then(callback(null, forms));
};

但是没有用。

2 个答案:

答案 0 :(得分:1)

如果您希望所有这些操作并行运行,则可以使异步操作合理化,然后使用Promise.all()来跟踪它们何时完成:

const util = require('util');

module.exports.getFilledOnlineFormsOfArray = (formIDs, callback) => {
    // make a promisified version of the method
    if (!this.getFilledOnlineFormByIDPromise) {
        this.getFilledOnlineFormByIDPromise = util.promisify(this.getFilledOnlineFormByID);
    }

    // use Promise.all() to track when all the promises have completed
    Promise.all(formIDs.map(id => {
        return this.getFilledOnlineFormByIDPromise(id);
    })).then(results => {
        callback(null, results);
    }).catch(err => {
        callback(err);
    });    
};

就个人而言,我将更改getFilledOnlineFormsOfArray()的接口以仅返回一个Promise,并完全停止使用回调来管理异步操作。您也可以从源头上修复this.getFilledOnlineFormByID()的实现,而不必在这里过多介绍。但是,我提供了一些可以与您显示的代码一起使用的东西。

注意:使用诺言时,最好使您的下层操作有义务,然后使用诺言实现所有控制流和错误处理。通常,它也容易得多(因为Promise特别擅长为您传播错误,而回调则不是)。在代码的更高级别混合使用回调和Promise会很快变得混乱不堪。

答案 1 :(得分:-1)

我们可以使用 async.parallel 来运行多个任务列表。

const async = require('async');

 module.exports.getFilledOnlineFormsOfArray = (formIDs, callback) => {
  let taskList = [];
  let forms = [];
  for (let i = 0; i < formIDs.length; i++) {
    taskList.push(function(cb){
      this.getFilledOnlineFormByID(formIDs[i], (err, filledForm) => {
          forms.push(filledForm);
          cb(err, filledForm)
       });
    });
  }
  async.parallel(taskList, function (errs, results) {
    if (errs) {
        console.log(errs);
    }
    console.log('Task list done.', results);
  })
};