Best way to wait for .forEach() to complete

Sometimes I need to wait for a .forEach() method to finish, mostly on 'loader' functions. This is the way I do that:

$q.when(array.forEach(function(item){ 
    //iterate on something 
})).then(function(){ 
    //continue with processing 
});

I can't help but feel that this isn't the best way to wait for a .forEach() to finish. What is the best way to do this?


Solution 1:

If there is no asynchronous code inside the forEach, forEach is not asynchronous, for example in this code:

array.forEach(function(item){ 
    //iterate on something 
});
alert("Foreach DONE !");

you will see the alert after forEach finished.

Otherwise (You have something asynchronous inside), you can wrap the forEach loop in a Promise:

var bar = new Promise((resolve, reject) => {
    foo.forEach((value, index, array) => {
        console.log(value);
        if (index === array.length -1) resolve();
    });
});

bar.then(() => {
    console.log('All done!');
});

Credit: @rolando-benjamin-vaz-ferreira

Solution 2:

The quickest way to make this work using ES6 would be just to use a for..of loop.

const myAsyncLoopFunction = async (array) => {
  const allAsyncResults = []

  for (const item of array) {
    const asyncResult = await asyncFunction(item)
    allAsyncResults.push(asyncResult)
  }

  return allAsyncResults
}

Or you could loop over all these async requests in parallel using Promise.all() like this:

const myAsyncLoopFunction = async (array) => {
  const promises = array.map(asyncFunction)
  await Promise.all(promises)
  console.log(`All async tasks complete!`)
}

Solution 3:

var foo = [1,2,3,4,5,6,7,8,9,10];

If you're actually doing async stuff inside the loop, you can wrap it in a promise ...

var bar = new Promise((resolve, reject) => {
    foo.forEach((value, index, array) => {
        console.log(value);
        if (index === array.length -1) resolve();
    });
});

bar.then(() => {
    console.log('All done!');
});