Reputation: 3181
So, I am creating an API in NodeJS. In one API, I have to call for loop within mongoose query.
How do I wait for the forEach to complete before executing res.send()? I have attached my code below.
router.post("/getResult", function (req, res) {
const lottery_id = req.body.lottery_id;
const prizeQuery = Prize.find({"lotid": lottery_id});
let response = [];
prizeQuery.exec(function (err, prizes) {
console.log(prizes.length);
if (err) return res.send({success: 0, data: err});
else {
prizes.forEach(prize => {
let prizeData = {};
const winnerQuery = Winner.find({"id": prize._id});
winnerQuery.exec(function (err, winners) {
if (err) return res.send({success: 0, data: err});
else {
prizeData = {
prize: prize,
winners: winners
};
response.push(prizeData);
}
});
});
}
});
return res.send({success:1, data: response});
});
In the code above, return is called before forEach is completed.
Upvotes: 2
Views: 1435
Reputation: 1042
@Rami's answer is correct but addition to that you can also use forof
for your code to work. forof
works synchronously so there will be no need for promise. like
for (let prize of prizes){
let prizeData = {};
try{
const winnerQuery = Winner.find({"id": prize._id});
const winners = await winnerQuery.exec()
prizeData = {
prize: prize,
winners: winners
};
response.push(prizeData);
}catch(err){
console.error(err)
}
}
Upvotes: 0
Reputation: 4643
Because you are running asynchronous code inside the forEach
and forEach
will not wait until the asynchronous code finish, to do so, you must wrap your async code with a waiting primitive.
Also the code you provided will call send
twice in case of failure, because the return inside the forEach
will not actually end the enclosing function.
try {
await Promise.all(prizes.map(async (prize) => {
const winners = await Winner.find({"id": prize._id});
response.push({prize, winners});
}))
res.send({success:1, data: response});
} catch (err) {
res.send({success: 0, data: err});
}
Upvotes: 6