When does Promise.all actually queue a microtask?

317 views Asked by At

So i am new to promises and i am trying some stuff to figure out what's going on under the hood. From what i read a Job is queued to the Microtask queue by .then immediately after the promise the method was chained to resolves.

Promise.resolve("FIRST")
  .then((m) => console.log(m))
  .then(() => console.log("FIRST on second level"))
  .then(() => console.log("FIRST on third level"))
  .then(() => console.log("FIRST on fourth level"));

Promise.resolve("SECOND")
  .then((m) => console.log(m))
  .then(() => console.log("SECOND on second level"))
  .then(() => console.log("SECOND on third level"))
  .then(() => console.log("SECOND on fourth level"));

Promise.all([
  Promise.resolve("Middle 1 resolved"),
  Promise.resolve("Middle 2 resolved"),
]).then((results) => console.log(results));

So ok, the first .then of the FIRST chain is queued immediately. The same goes for the first of the SECOND chain. But they both return promises which will be pending until the first two queued jobs get executed. So why is the log like this:

FIRST
SECOND
FIRST on second level
SECOND on second level
[ 'Middle 1 resolved', 'Middle 2 resolved' ]
FIRST on third level
SECOND on third level
FIRST on fourth level
SECOND on fourth level

Why isn't the "middle" log placed before "FIRST on second level"? Because i was assuming from what i read that the promise returned from Promise.all IN THIS EXAMPLE will resolve as long as the stack is empty and therefore its .then will get queued right after the first two:

then(m => console.log(m)) //on line 2 and line 8

So where am i wrong? What am i missing or don't understand properly? Thank you in advance!

1

There are 1 answers

1
Nicholas Tower On BEST ANSWER

Promise.all creates a new promise, and for it to know when to resolve that promise, it needs to call .then on each of the promises you pass into it. So first the promises in the array must resolve, then the promise created by Promise.all can resolve, and only then do does your console.log get called.

In other words, there are 2 levels of calls to .then, much like your other second level examples. It's just that one level is hidden inside the implementation of Promise.all

If it helps, here's an approximation of what Promise.all is doing:

function all(promises) {
  return new Promise((resolve) => {
    let count = 0;
    let results = [];
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(result => {
        count++;
        results[i] = result;
        if (count === promises.length) {
          resolve(results);
        }
      });
    }
  });
}