这个问题在这里已有答案:
我正在使用forEach循环将一些数据推送到数组并将其发送到客户端
var arrayToSend = [] //Empty Array
SomeArray.forEach(function(item){
Collection.findById(item.id,function (err,data) {
if (err) {
console.log(err)
} else {
arrayToSend.push(data.record)
}
//How can I run this next line at end of loop asynchronously
res.render("index",{arrayToSend : arrayToSend })
})
})
}
如何在回调形式的forEach作用域内循环结束之后使用async来运行res.render(“index”,{arrayToSend:arrayToSend}),否则如果我在循环外运行它将发送空数组?
使用.forEach
将.map
中的每个项目映射到Promise,而不是使用someArray
,这样就可以创建一个Promises数组。如果你在该数组上调用Promise.all
,那么当数组中的所有promise都已解决时,你将得到一个Promise。
因为findById
是基于回调的,而不是基于Promise的,所以你需要先将每个回调转换为Promise:
const promises = someArray.map((item) => new Promise((resolve, reject) => {
Collection.findById(item.id, (err,data) => {
if (err) return reject(err);
resolve(data.record);
});
}));
Promise.all(promises)
.then(arrayToSend => {
res.render("index", { arrayToSend });
})
.catch((err) => {
// handle errors
});
如果你想容忍来自findById
的错误并仍然构建一个没有错误的项目的arrayToSend
,你可以push
到一个外部数组(类似于你原来的做法)和resolve
无条件,无论findById
是否导致错误:
const arrayToSend = [];
const promises = someArray.map((item) => new Promise((resolve, reject) => {
Collection.findById(item.id, (err,data) => {
if (err) console.log(err);
else arrayToSend.push(data.record);
resolve();
});
}));
Promise.all(promises)
.then(() => {
res.render("index", { arrayToSend });
})