It's better to write code that doesn't rely on the timing of immediate callbacks (like microtasks vs macrotasks), but let's put that aside for the moment.
setTimeout
queues a macrotask, which, at a minimum, waits to start until all microtasks (and microtasks that they spawn) finish. Here's an example:
console.log('Macrotask queued');
setTimeout(function() {
console.log('Macrotask running');
});
Promise.resolve()
.then(function() {
console.log('Microtask running');
});
console.log('Microtask queued');
console.log('Last line of script');
The behavior of a .then
on a resolved Promise is fundamentally different from the behavior of an immediate setTimeout
callback - the Promise .then
will run first, even if the setTimeout
was queued first. But only modern browsers support Promises. How can the special functionality of a microtask be properly polyfilled if Promise
doesn't exist?
If you try to imitate a .then
's microtask by using setTimeout
, you'll be queuing a macrotask, not a microtask, so the badly-polyfilled .then
won't run at the right time if a macrotask is already queued.
There's a solution using MutationObserver
, but it looks ugly, and isn't what MutationObserver
is for. Also, MutationObserver
is not supported on IE10 and earlier. If one wants to queue a microtask in an environment that doesn't natively support Promises, are there any better alternatives?
(I'm not actually trying to support IE10 - this is just a theoretical exercise on how microtasks can be queued without Promises)
from How to queue a microtask if the browser doesn't support native Promises?
No comments:
Post a Comment