I'd like to know the order in which the JavaScript code below is executed and why. In particular, I would like to learn more about the contents of the code that goes into the microtask queue, focusing on step-by-step
var promise = Promise.resolve();
promise = promise.then(function(rtnVal) {
console.log('1');
var promise2 = Promise.resolve();
promise2 = promise2.then(function(rtnVal) {
console.log('2');
});
promise2 = promise2.then(function(rtnVal) {
console.log('3');
});
console.log('4');
});
promise = promise.then(function(rtnVal) {
console.log('5');
var promise2 = Promise.resolve();
promise2 = promise2.then(function(rtnVal) {
console.log('6');
});
promise2 = promise2.then(function(rtnVal) {
console.log('7');
});
console.log('8');
});
console.log('9');
Here's what I did: 9,1,4,2,5,8,3,6,7 ->I'm wondering why it runs in this order`
Some things to be aware of:
then
callbacks (if any) are put on the PromiseJob queuethen()
is called (not its callback), the returned promise is always pending, even if that then()
call is made on a resolved promise. This is because the returned promise can only be resolved by executing the callback that is given to the then
method since it determines how the promise will resolve, but which can only execute asynchronously.To ease the analysis, I modified your script to give a name to each promise (a
to i
) and to each callback function (a_then
, ...), but the logic and output remains the same:
var a = Promise.resolve();
var b = a.then(function a_then() {
console.log(1);
var c = Promise.resolve();
var d = c.then(function c_then() {
console.log(2);
});
var e = d.then(function d_then() {
console.log(3);
});
console.log(4);
});
var f = b.then(function b_then() {
console.log(5);
var g = Promise.resolve();
var h = g.then(function g_then() {
console.log(6);
});
var i = h.then(function h_then() {
console.log(7);
});
console.log(8);
});
console.log(9);
Here is a sequence of events that happen during the execution of that code.
a
to i
represent the state of the promise with that name: ?
for pending, F
for fulfilled.Here we go:
Task | Action | a | b | c | d | e | f | g | h | i | PromiseJob queue |
---|---|---|---|---|---|---|---|---|---|---|---|
Script | a = Promise.resolve() |
F | - | - | - | - | - | - | - | - | |
Script | b = a.then(a_then) |
F | ? | - | - | - | - | - | - | - | a_then |
Script | f = b.then(b_then) |
F | ? | - | - | - | ? | - | - | - | a_then |
Script | console.log(9) |
F | ? | - | - | - | ? | - | - | - | a_then |
Host | dequeue a_then |
F | ? | - | - | - | ? | - | - | - | |
a_then |
console.log(1) |
F | ? | - | - | - | ? | - | - | - | |
a_then |
c = Promise.resolve() |
F | ? | F | - | - | ? | - | - | - | |
a_then |
d = c.then(c_then) |
F | ? | F | ? | - | ? | - | - | - | c_then |
a_then |
e = d.then(d_then) |
F | ? | F | ? | ? | ? | - | - | - | c_then |
a_then |
console.log(4) |
F | ? | F | ? | ? | ? | - | - | - | c_then |
a_then |
return resolves b |
F | F | F | ? | ? | ? | - | - | - | c_then , b_then |
Host | dequeue c_then |
F | F | F | ? | ? | ? | - | - | - | b_then |
c_then |
console.log(2) |
F | F | F | ? | ? | ? | - | - | - | b_then |
c_then |
return resolves d |
F | F | F | F | ? | ? | - | - | - | b_then , d_then |
Host | dequeue b_then |
F | F | F | F | ? | ? | - | - | - | d_then |
b_then |
console.log(5) |
F | F | F | F | ? | ? | - | - | - | d_then |
b_then |
g = Promise.resolve() |
F | F | F | F | ? | ? | F | - | - | d_then |
b_then |
h = g.then(g_then) |
F | F | F | F | ? | ? | F | ? | - | d_then , g_then |
b_then |
i = h.then(h_then) |
F | F | F | F | ? | ? | F | ? | ? | d_then , g_then |
b_then |
console.log(8) |
F | F | F | F | ? | ? | F | ? | ? | d_then , g_then |
b_then |
return resolves f |
F | F | F | F | ? | F | F | ? | ? | d_then , g_then |
Host | dequeue d_then |
F | F | F | F | ? | F | F | ? | ? | g_then |
d_then |
console.log(3) |
F | F | F | F | ? | F | F | ? | ? | g_then |
d_then |
return resolves e |
F | F | F | F | F | F | F | ? | ? | g_then |
Host | dequeue g_then |
F | F | F | F | F | F | F | ? | ? | |
g_then |
console.log(6) |
F | F | F | F | F | F | F | ? | ? | |
g_then |
return resolves h |
F | F | F | F | F | F | F | F | ? | h.then |
Host | dequeue h_then |
F | F | F | F | F | F | F | F | ? | |
h_then |
console.log(7) |
F | F | F | F | F | F | F | F | ? | |
h_then |
return resolves i |
F | F | F | F | F | F | F | F | F | |
Host | queue is empty | F | F | F | F | F | F | F | F | F |