I read some files about the microtask and macrotask queue. I know that the callback function of a resolved promise is added to the microtask, same as the other sync tasks. But the following code:
fetch=() => new Promise ((resolve) => resolve ({m: 121}))
function x() {
let d = 3;
fetch().then((data) => {
d = data.m;
console.log("b", d);
});
console.log("a", d);
}
x();
gives a result of
a 3
b 124
IAs I thought, since fetch here fetches a "local" file and it takes no time, so the callback function is immediately added to the microtask queue, and then console.log("a", d);
is added to the microtask queue. If so, the result should be
b 124
a 124
So what is the reason for the real result? Why the call back function is executed after console.log("a", d);
?
CodePudding user response:
Whether or not a callback is added to the microtask queue or the callback queue has nothing to do with how long it takes to run. The Promise
callbacks are always added to the microtask queue. Regardless of how long it takes. And, the queue is cleared, after the call stack is empty. In your example, the function x
has to complete execution before your Promise
callback can run. So, a
is logged first.
Read more about the event loop here. But in a nutshell, browser API callbacks go in the callback queue, and higher priority callbacks like the Promise
callbacks go in the microtask queue. The queues are cleared only after the call stack is empty.
This can lead to puzzling behaviors like the following code running forever since the call stack never becomes empty.
let flag = true;
setTimeout(() => flag = false, 200)
while (flag) console.log('hello')