skip to Main Content

I was reading about nested promises and encountered this coding challenge in the tutorials. Can someone explain the execution order of this code?

new Promise((resolve) => {
    new Promise((res) => {
        console.log("c");
        resolve(3);
        res(2);
    }).then((response) => console.log(response))
}).then((res) => console.log(res));

I have ran the code and the output was:

c
2
3

But I was expecting that the output should be this:

c
3
2

because the outer promise is resolved first and then the inner promise is resolved later.

3

Answers


  1. In short, it’s because of the order that you’re calling .then.

    new Promise((resolve) => {
        new Promise((res) => {
            console.log("c");
            resolve(3);
            res(2);
    

    In the above code we enter the outer constructor, which immediately calls the outer function. This then creates the inner promise, calling the inner function. The inner function logs "c", then resolves the outer promise to 3, and then resolves the inner promise to 2.

    So at this point we have 2 resolved promises, but no code that’s trying to do anything with them.

    }).then((response) => console.log(response))
    

    Having finished constructing the inner promise, we call .then on the inner promise. Since the promise is resolved, this queues up a microtask to run.

    }).then((res) => console.log(res));
    

    Having finished constructing the outer promise, we call .then on the outer promise. Since the promise is resolved, this queues up a microtask to run.

    Now we’ve finished running all synchronous code. The call stack empties and microtasks run. These are executed first in first out, so the microtask related to the inner promise runs first, logging out 2. Then the remaining microtask runs and logs out 3.

    Login or Signup to reply.
  2. In addition to Nicholas’ answer, you’re possibly being tripped up by the reuse of the identifier ‘res’. The first use in the inner Promise is as a callback, where it returns the value 2 to the Promise.
    The second use on the final line is in a different scope, and is used as the parameter name in the .then() for the outer Promise.
    If you replace both uses of ‘res’ on the final line with ‘outerPromiseResult’, it might help to clear things up.

    Login or Signup to reply.
  3. The initial outer function invokes an inner function, which contains a resolve(3) call without an immediate return, followed by a res(2) call. These calls are placed in the microtask queue to be executed once the call stack is clear. The inner function must complete before the outer function can fully conclude. Consequently, the microtask queue contains:

    1. res(2)
    2. resolve(3)
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search