2

I am confused of the output of this code. The output is 4 3 2 1

How do I understand the flow?

new Promise(resolve => {
    resolve(1);
    Promise.resolve().then(() => console.log(2));
    console.log(4);
}).then( t => console.log(t) );
console.log(3);
Nishant
  • 20,354
  • 18
  • 69
  • 101
R.hui
  • 523
  • 1
  • 4
  • 8
  • 2
    synchronous code remains synchronous, asynchronous code remains asynchronous - you can see the execution sequence of the console.log's from the output – Jaromanda X Feb 14 '18 at 08:19
  • 1, 2, 3 (up to .then), 4, 5 (up to .then) 6,3 (code inside .then), 5 (code inside .then) - or, see https://jsfiddle.net/gzy6ncz3/ – Jaromanda X Feb 14 '18 at 08:23
  • What output did you expect? There are links to a video and some documentation in [this](https://stackoverflow.com/a/47678417/1641941) answer that could help. – HMR Feb 14 '18 at 09:16
  • Thinking of `resolve()` doing something like a `setTimeout(later, 0)` where `later` is then function registered using `then` could be a good way to reason about what is happening no? I mean that is what it meas to say this is `asynchronous`. It gets pushed to the event-loop right? – Nishant Feb 14 '18 at 12:50

2 Answers2

3

I think the key understandings are

  • a new Promise callback is always invoked synchronously (during the call)
  • a then callback is always invoked asynchronously (later)

So the individual synchronous steps here are, in order:

new Promise(resolve => { // begins creating a promise
    resolve(1);          // fulfills the promise
    Promise.resolve()    // creates a promise
    .then(…);            // registers a callback
    console.log(4);      // logs the first line
})                       // finishes the promise creation
.then(…);                // registers a callback
console.log(3);          // logs the second line

When the callbacks are registered, then checks whether the promise is already settled, and this is the case here (for both promises), it immediately schedules them by putting them on a queue. In theory this queue defines a specific order, in practice you should ignore that (i.e. things scheduled at the same time can happen in any order). If you want a specific order, always make an explicit promise chain instead of relying on internal queuing.

So here we have two scheduled items:

() =>          // the first item is called with undefined (result of `Promise.resolve()`)
console.log(2) // logs the third line

t =>           // the second item is called with 1 (from the `resolve(1)` call)
console.log(t) // logs the fourth line
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

This depends on the way Promise is implemented. Promises/A+ specification needs the function registered using then, say later, to be done asynchronously.

So, thinking of resolve(1) doing something like the below can help you reason about the asynchronous flow explained in the above comments:

  1. Set the promise's value to 1
  2. Register a setTimeout(later, 0), where later is the function registered by then

setTimeout is the key, it just pushes it to the event-loop instead of doing it right away because spec says so.

So in,

new Promise(resolve => {
    resolve(1);
    Promise.resolve().then(() => console.log(2));
    console.log(4);
}).then( t => console.log(t) );
console.log(3);

console.log(2) // gets queued
console.log(4) // gets executed
console.log(3) // gets executed
console.log(1) // gets queued

You can see a related questions here: Why do Promise libraries use event loops?

Nishant
  • 20,354
  • 18
  • 69
  • 101