0

I am trying to wrap my head around working of javascript asynchronous functions in loop. Please follow the code snippet below

const sleep = async(delay, input) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(input);
    }, delay);
  });
};

const promises = [sleep(500, 1), sleep(1000, 3), sleep(750, 2)];

(async() => {
  console.time('runTime');
  const res1 = [];
  const res2 = [];

  promises.forEach(async(promise) => {
    const res = await promise;
    res1.push(res);
  });

  console.log('logging forEach loop response-1', res1);

  for (const promise of promises) {
    const res = await promise;
    res2.push(res);
  }

  console.log('logging forEach loop response-2', res1);
  console.log('logging for loop response', res2);

  console.timeEnd('runTime');
})();

The output printed for above snippet is as below

logging forEach loop response-1 []
logging forEach loop response-2 [ 1, 2, 3 ]
logging for loop response [ 1, 3, 2 ]
runTime: 1.011s

Why is the order of output is different in forEach response-2 than in for response? Any explanation will be very helpful.

EDIT: My apologies for the vauge question earlier. But there are two queries in particular which I am not able to unravel

  1. How the whole snippet takes ~1s to execute. I understand the logging forEach loop response-1 logs the empty array because callbacks in forEarch are async but entire forEach is not, and array is not yet populated after forEach has finished. But in the case of for-of loop shouldn't it have taken ~2.25s to execute, because it awaits for 0.5s, 1s and 0.75s respectively in each iteration?

  2. How the sequence of output logged in logging forEach loop response-2 is in the order of delay as opposed to for-of loop. Is it because in forEach an separate instance of anonymous callback is created and each callback is resolved in order of delay and hence the output. But if that's the case the my question #1 still unclear why for-of loop takes ~1s and not ~2.25s.

In this post I am able to understand the reason for #2 partially but still as per my understanding and what I read, why the runtime of for-of loop is not ~2.25s?

pythoniesta
  • 317
  • 6
  • 19
  • 1
    "*in the case of for-of loop shouldn't it have taken ~2.25s to execute, because it awaits for 0.5s, 1s and 0.75s respectively in each iteration?*" - that's because you started all the `setTimeout`s when you called `sleep` in `const promises = [sleep(500, 1), sleep(1000, 3), sleep(750, 2)];` - all at once, sleeping concurrently. A promise represents the result, not a task that is executed (again) when you `await` it. If you moved the `sleep` calls into the `for` loop (e.g. `for (const t of [500, 1000, 750]) await sleep(t)`) , the timeouts would be sequential. – Bergi Mar 23 '23 at 19:19
  • 1
    "*How the sequence of output [of `res1` is in] order of delay? Is it because in forEach an separate instance of anonymous callback is created and each callback is [invoked] in order of delay?*" - yes. – Bergi Mar 23 '23 at 19:21
  • many thanks @Bergi!!, this was very helpful especially the distinction of creating array with sleep as to calling it inside `for` loop. – pythoniesta Mar 24 '23 at 04:41

0 Answers0