I didn’t return something in then() callback, In my opinion the output should be 1 5 7 2 6 3 4,but the result is 1 2 5 3 6 7 4, who can tell me why
Promise.resolve().then(function() { console.log('promise1'); Promise.resolve().then(() => { console.log('promise2') Promise.resolve().then(() => { console.log('promise3') Promise.resolve().then(() => { console.log('promise4') }) }) }) }).then(function() { console.log('promise5'); Promise.resolve().then(() => { console.log('promise6') }) }).then(() => { console.log('promise7') })
Advertisement
Answer
Alright, this will be very verbose. Contrary to others, i’ll claim, that the execution order for the console.log
calls is completely deterministic here. This doesn’t always have to be the case with async code, but when there isn’t any “real” async code happening, it still often is.
Code numbered for clarity:
01 Promise.resolve().then(function() { 02 console.log('promise1'); 03 04 Promise.resolve().then(() => { 05 console.log('promise2') 06 07 Promise.resolve().then(() => { 08 console.log('promise3') 09 10 Promise.resolve().then(() => { 11 console.log('promise4') 12 }) 13 }) 14 }) 15 }).then(function() { 16 console.log('promise5'); 17 18 Promise.resolve().then(() => { 19 console.log('promise6') 20 }) 21 }).then(() => { 22 console.log('promise7') 23 })
Reminder: Javascript is single-threaded, only one can run at the same time.
In the following, each step is code execution until the context is released, plus promise resolving because of the function returning. Some calls are omitted (e.g. Promise.resolve()
), because it’s kind of obvious, what happens.
At the end of each step, i’ll list the current queue, and already executed comment.log
calls. As every function begins with a console.log
call, with a unique number, i’ll use those as names for the functions as well.
Note: When a function ends, which in turn resolves a promise, which has empty [[PromiseFulfillReactions]]
, i won’t mention it, as it’s not important.
Program starts running…
01 Promise.resolve().then(function() {
is called and enqueues1
15 }).then(function() {
is called on an unresolved promise (from thethen
in line 1), wait for it to resolve21 }).then(() => {
is called on an unresolved promise (from thethen
in line 15), wait for it to resolve
Queued tasks: [1]
Already performed logs: []
02 console.log('promise1');
executes04 Promise.resolve().then(() => {
is called and enqueues2
- Returning
undefined
, a non-object (certainly not then-able, not a promise), causes resolving of the promise returned fromthen
in line 1, which in turn causes its[[PromiseFulfillReactions]]
to be performed. The only added reaction is from15 }).then(function() {
(see above). This enqueues5
.
Queued tasks: [2, 5]
Already performed logs: [1]
05 console.log('promise2')
executes07 Promise.resolve().then(() => {
is called and enqueues3
Queued tasks: [5, 3]
Already performed logs: [1, 2]
16 console.log('promise5');
executes18 Promise.resolve().then(() => {
is called and enqueues6
- Returning, similar to above, resolves the promise returned from
15 }).then(function() {
, so its[[PromiseFulfillReactions]]
are performed. This enqueues7
Queued tasks: [3, 6, 7]
Already performed logs: [1, 2, 5]
08 console.log('promise3')
executes10 Promise.resolve().then(() => {
is called and enqueues4
Queued tasks: [6, 7, 4]
Already performed logs: [1, 2, 5, 3]
I’ll add the last steps for completion’s sake, but from here it’s very straight forward.
19 console.log('promise6')
is executed
Queued tasks: [7, 4]
Already performed logs: [1, 2, 5, 3, 6]
22 console.log('promise7')
is executed
Queued tasks: [4]
Already performed logs: [1, 2, 5, 3, 6, 7]
11 console.log('promise4')
is executed
Queued tasks: []
empty!
Already performed logs: [1, 2, 5, 3, 6, 7, 4]
program terminates.