Based on this accepted answer regarding micro-task queue checkpoints in JS and looking up the concept more, I have come to understand the following:
Micro-task queue checkpoints happen at these points in the event loop:
To understand this via an example, I tried the following code example:
setTimeout(() => {
console.log('timeout1');
}, 3000);
setTimeout(() => {
console.log('timeout2');
}, 3000);
let promise = new Promise(function (resolve, reject) {
setTimeout(() => resolve('promise!'), 3000);
});
promise.then(
(result) => console.log(result),
(err) => console.log(err)
);
According to the concept of event-loops in JS, setTimeouts functions are pushed to the macro-task queue after the designated time passes. Thus, all three setTimeout tasks should be pushed on to the macro-task queue after 3 seconds have elapsed. On the other hand, the function passed to the .then() of the promise should be pushed to the micro-task queue. For the above code, at the beginning of a subsequent cycle, the first setTimeout task that was pushed to the macro-task queue should be run to print 'timeout1'.
According to the micro-task queue checkpoint concept that I provided above, thereafter a checkpoint should occur and the print function in the micro-task queue should print 'promise!'.
Finally, the second macro-task on the macro-task queue 'timeout2' should be printed.
However, running the code on the console of Chrome and Firefox (latest versions), and via Node v16.14.0 on my machine, I find the order of printing to be:
timeout1
timeout2
promise!
Is micro-task queue checkpoint behavior not guaranteed? If it is, am I mistaken somewhere else in my evaluation?
Thus, all three
setTimeout
tasks should be pushed on to the macro-task queue after 3 seconds have elapsed. On the other hand, the function passed to the.then()
of the promise should be pushed to the micro-task queue.
No, that does not happen until the promise is actually fulfilled, during the execution of the third timer macro task.
You get a better understanding of the order by fulfilling the promise from the second timer:
setTimeout(() => {
console.log('timeout1');
}, 1000);
new Promise(function (resolve, reject) {
setTimeout(() => {
console.log('timeout2');
resolve('promise from timeout2');
}, 1000);
}).then(
(result) => console.log(result),
(err) => console.log(err)
);
setTimeout(() => {
console.log('timeout3');
}, 1000);