Reputation: 259
When I run this code in Firefox and Chrome, the results are different:
function run() {
setTimeout(() => console.log("1"), 0);
setTimeout(() => console.log("2"), 100);
let start = Date.now();
while (Date.now() - start < 200) {
// do nothing
}
setTimeout(() => {
console.log("3");
}, 0);
start = Date.now();
while (Date.now() - start < 200) {
// do nothing
}
setTimeout(() => {
console.log("4");
}, 0);
}
run();
In Chrome (and Node.js), this is printed:
1
3
2
4
In Firefox, this is printed:
1
2
3
4
But if I remove the line 2 (setTimeout(() => console.log("1"), 0);
), then the same thing is printed on every platform:
2
3
4
How to explain these different results?
Thanks!
Upvotes: 3
Views: 526
Reputation: 155704
The details of when deferred "messages" are added to the event loop message queue are implementation details, not documented guarantees. By the time your function yields control back to the event loop, all of your setTimeout
call are eligible to execute (three of them were scheduled to run immediately, one of them was scheduled to run in 100 ms) and you've guaranteed it's been at least 400 ms since you scheduled it.
The difference between the two could be as simple as whether they choose to look for deferred tasks that have become ready (to move from the deferred queue to the main "ready to go" message queue) immediately before or immediately after new items are inserted in the main message queue. Chrome chooses to move immediately after 3
is scheduled (so 3
goes in, then the deferred 2
), Firefox immediately before (moving in 2
before it puts 3
in).
Both of them could change in the next release without violating any documented guarantees. Don't rely on it, don't expect it to be stable. While immediately scheduled tasks are guaranteed to execute in FIFO order, there are no guarantees on when deferred tasks get moved onto the "ready-to-go" message queue. The spec seems to requires that 1
, 3
and 4
execute in that order (since they were all immediately ready, not deferred), with only the ordering of 2
being flexible, but even that isn't a true guarantee; it can get weird with the various ways in which an "immediate" setTimeout
task may not actually be scheduled immediately.
You may be interested in the MDN docs on why setTimeout
can take longer than expected; it explains by side-effect a lot of how the event loop works, even as it carefully provides no guarantees on the details you're exploring.
Upvotes: 3
Reputation: 1806
I can't give you an full detailed explanation, but the second paramter of setTimeoput
and setInterval
doesn't mean, it will exactly execute it at that time. They will put it in a queue, so the background can execute it.
The browser has a lifecycle when to execute specific steps to update the data and the styles.
I can only send you this youtube link, that helped me to learn more about it:
https://www.youtube.com/watch?v=MCi6AZMkxcU
Upvotes: 1