0

I am trying to call a request inside of a forEach loop, but my code is exiting the loop before the loop is done. Is there a way to ensure the loop finishes before the next code is executed? (I am relatively new to promises)

My code follows this format:

let arr = [1, 2, 3, 4, 5, 6];

arr.forEach(num => {
  return request('http://google.com')
    .get('/')
    .then(() => {
      console.log(num);
    });
});
console.log('HERE');

This code ^ logs

HERE
1
2
6
4
5
3

(the numbers are in random order, that's not really what matters to me)

but I want it to log

1
2
3
4
5
6
HERE

How do I do this?

  • Possible duplicate of [Callback after all asynchronous forEach callbacks are completed](https://stackoverflow.com/questions/18983138/callback-after-all-asynchronous-foreach-callbacks-are-completed) – takendarkk Jan 18 '19 at 17:34
  • Code is not exiting the loop before it is done, that is how asynchronous code works. You triggered a bunch of asynchronous calls and than it stops. The calls finish after the loop has been finished. – epascarello Jan 18 '19 at 17:44

2 Answers2

3

You can't use forEach in a situation like this.

Instead, since you're using promise-based concurrency, you'll have to turn each request into a Promise (arr.map(num => ...)), then wrap all of them in Promise.all, which itself returns a promise that resolves after all of the wrapped promises resolve.

let arr = [1, 2, 3, 4, 5, 6];

Promise.all(
  arr.map(num =>
    request("http://google.com")
      .get("/")
      .then(() => {
        console.log(num);
      })
  )
).then(() => {
  console.log("HERE");
});
AKX
  • 152,115
  • 15
  • 115
  • 172
  • 1
    This will only produce the desired result if the requests come back in order. – Mark Jan 18 '19 at 17:37
  • 1
    Not really, the promises can be resolved in any order, they're already being sorted when the mapping occurs. But if any of those fail, the 'Promise.all()` will fail too. – Guy who types fast Jan 18 '19 at 17:43
  • @Guywhotypesfast sure in the end that map result will hold values in order, but the `console.logs` will happen in the order resolved. – Mark Jan 18 '19 at 17:45
  • Humm, you are right, the logs will occur when each promise is resolved. returning the array and logging inside the `.then()` callback would solve this. Right? – Guy who types fast Jan 18 '19 at 17:47
  • I just noticed: `(the numbers are in random order, that's not really what matters to me)` so it probably doesn't matter. – Mark Jan 18 '19 at 17:48
2

Another example here. You can use also for

let array = [1, 2, 3, 4, 5, 6];
async function processArray(arr){
  for (const num of array) {
    await request('http://google.com').get('/');
    console.log(num);
  }
  console.log('Done!');
}

processArray(array);
Skraloupak
  • 374
  • 4
  • 5