With regard to the execution order of Promise and setTimeout, I feel that my understanding of eventloop is wrong.
look at the code:
setTimeout(() => {
console.log(1);
Promise.resolve().then(() => {
console.log(4);
});
});
Promise.resolve().then(() => {
console.log(2);
setTimeout(() => {
console.log(3);
});
});
Please output the above execution result:.
browser output: 21 43,
node output: 21 34
this makes me a little confused.
The order of
2 and 1 can be understood, but the order and feeling of 4 and 3 conflict with the knowledge they understand.
my understanding is that the code executes from top to bottom,
puts the first timer in the event callback queue,
puts the first peomise.then in the micro-task,
then executes the code in the micro-task, first outputs 2,
and then plugs the second timer into the event callback queue,
at this time the main thread is idle, take the callback execution of the first timer in the event callback queue, print 1,
then put the promise into the micro-task, and the
divergence occurs at this time, when the main thread or the execution stack is to take the promise from the micro-task to print 4 or to print 3 with the function of out of the timer.
from the result, print 3 is selected for the execution stack
from an article by the ele.me team, I read that node will clear the queue at the current stage, that is, perform all task, and then check the micro tasks
hope to solve the puzzle, whether it is the browser or the node end, it doesn"t make sense according to my way of thinking.
browser-side loop policy: first execute the current loop macro task, and then execute the micro task under this macro task (h5).
node loop policy: first execute the timer queue of this loop, and then execute the micro task (libuv) under timer.
in your case, the macro tasks are: the current code block, and the setTimeout, micro tasks are: Promise.
so, the browser's behavior is to first execute the macro task of the entire code block, and then perform the micro task under the macro task, that is, (Promise.resolve (). Then) in this case, there is one and only one. Therefore, the first output 2, the end of this cycle.
the second loop finds the macro task (the first setTimeout), prints out 1, then executes all the micro tasks under the macro task, prints out 4, and the second loop ends.
the third loop, find the second setTimeout, to print out 3, and the third loop ends, so the output on the browser side is 2 1 4 3.
while the node side begins to behave the same as the browser, executing the entire block of code, completing the micro task, and outputting 2. Then find the two timer, in the second cycle and output them in turn. After all the timer at the current level is executed, Timer micro task 4 is executed, so the output on the Node side is 2 1 3 4.
Summary:
browser: code block (macro task) = > micro task promise (output 2) = > first timer (output 1) = > micro task promise (output 4) = > second timer (output 3)
node: code block = > micro task promise (output 2) = > first timer (output 1) = > second timer (output 3) = > micro task promise (output 4)
setImmediate (() = > {
console.log (1);
process.nextTick (() = > {
console.log(4);
});
});
process.nextTick (() = > {
console.log (2);
setImmediate (() = > {
console.log(3);
});
});
this code is mentioned in that article. The article says that the output is 2134
, but you will find that you throw it into the latest version of node and the output is 2143
. The older version is 2134, which indicates that the asynchronous execution mechanism of node has changed. It is not what the article said
.
at this time, the main thread is idle, take out the callback execution of the first timer in the event callback queue, print 1,
, and then put the promise into the micro task.
then there is a disagreement. At this time, the main thread or the execution stack should take out the promise from the micro task to execute print 4 or take out the timer function to print 3;
I think here, when printing 1 and placing the promise after the micro task, the task stack is empty. Once the task stack is empty, it will immediately check the micro task, print 4,
then the task stack is empty again, continue to check the micro task, is also empty, and then take out the timer
again.
that is, when multiple setTimeout
calls arrive at the time and want to return to the stack for execution, they execute one, clear the stack, and then execute the next
.
Video reference (location of this time): https://youtu.be/8aGhZQkoFbQ?.