Reputation: 509
I would like to run a function after the for loop done looping, but in my case the function after the for loop runs before the loop even finished. Here's my code
let orderedItems = [];
for (let i = 0; i < orderCode.length; i++) {
menuModel.findOne({
_id: orderCode[i]
}, (err, order) => {
if (order) {
orderedItems.push(order.name);
}
});
}
console.log(orderedItems); // all the tasks below run before the loop finished looping
let orderData = new orderModel();
orderData._id = helpers.createRandomString(5).toUpperCase();
orderData.username = username;
orderData.orderCode = orderCode;
orderData.orderedItems = orderedItems;
orderData.totalPrice = 5;
orderData.save((err) => {
if (err) {
console.log(err);
callback(500, {
'Error': '1'
});
}
callback(200, {
'Message': 'Successfully ordered'
});
});
Upvotes: 1
Views: 192
Reputation: 3452
as @RishikeshDhokare said everything is executed asynchronously. so the trick is to split the tasks into separate functions.
so first we execute an async function you can use promises or async await
then we say after all the async tasks have been completed do the save task.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
const orderCode = [1, 2, 3]
const menuModel = {
findOne: item => new Promise(resolve => resolve({
_id: item._id,
name: 'name'
}))
}
class orderModel {
save(cb) {
return cb(null)
}
}
/*
ignore all above here i'm mocking your funcs
and vars so that the code works
*/
let orderedItems = [];
function getAllOrderedItems() {
const promises = orderCode.map(id => {
return menuModel.findOne({
_id: id
});
})
console.log('...start the request')
// fire all async items then resolve them all at once
return Promise.all(promises)
.then((data) => {
console.log('...finished all requests')
return orderedItems.concat(data);
})
.catch(err => console.log(err))
}
function handleSave(data) {
let orderData = new orderModel();
console.log(data)
console.log('...start save')
orderData.save((err) => {
console.log('...save finished')
});
}
//do all the async tasks then do the save task
getAllOrderedItems()
.then((data) => handleSave(data))
Upvotes: 2