Kemal Dwiheldy
Kemal Dwiheldy

Reputation: 509

Run a function after a loop

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

Answers (1)

Joe Warner
Joe Warner

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

Related Questions