我正在尝试等待多次回调,但我无法找到一种方法来做得很好。
我的代码是:
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));
};
但它不起作用。
如果您希望所有这些操作并行运行,您可以宣传您的异步操作,然后使用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()
的实现,而不是在这里宣传它。但是,我提供了一些可以与您展示的代码一起使用的东西。
注意:使用promises时,最好先实现较低级别的操作,然后使用promises实现所有控制流和错误处理。它通常也容易得多(因为promises特别擅长为你传播错误,而回调则不然)。在更高级别的代码中混合回调和承诺可能会很快变得混乱。
我们可以使用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);
})
};