我在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
有没有办法在执行循环外的其余代码之前等待,如果是这样,我将如何去做。
答案 0 :(得分:1)
假设db
是访问数据库的某个模块,请尝试查找同步版本。这假设您可以使用同步,因为您尝试以这种方式编写它,等待所有事情再继续。
如果您的数据库库使用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
});
如果您没有承诺返还API的版本,请将db.findApp
包含在承诺中,请执行建议#2。
function promiseReturningFindApp(id){
return new Promise((resolve, reject) => {
db.findApp(id, (error, result) => {
if(error) reject(error);
else resolve(result);
});
});
}
选项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创建类似的东西,但这需要更少的代码行。