Es mejor escribir código que no se base en el momento de las devoluciones de llamadas inmediatas (como microtasks vs macrotasks), pero dejemos eso de lado por el momento.
setTimeout
pone en cola un macrotask, que, como mínimo, espera comenzar hasta que finalicen todos los microtasks (y los microtasks que generan). Aquí hay un ejemplo:
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');
El comportamiento de una .then
Promesa resuelta es fundamentalmente diferente del comportamiento de una setTimeout
devolución de llamada inmediata : la Promesa .then
se ejecutará primero, incluso si setTimeout
primero se puso en cola. Pero solo los navegadores modernos admiten Promesas. ¿Cómo puede la funcionalidad especial de un microtask ser debidamente rellenada si Promise
no existe?
Si intentas imitar la microtask de un usuario .then
usando setTimeout
, estarás haciendo cola con una macrotask, no con una microtask, por lo que el mal polifundido .then
no se ejecutará en el momento adecuado si una macrotask ya está en cola.
Hay una solución que usa MutationObserver
, pero se ve fea y no MutationObserver
es para lo que sirve. Además, MutationObserver
no es compatible con IE10 y versiones anteriores. Si se quiere poner en cola una microtask en un entorno que no admite Promesas de forma nativa, ¿hay alguna alternativa mejor?
(En realidad, no estoy tratando de admitir IE10; este es solo un ejercicio teórico sobre cómo se pueden poner en cola las microtask sin Promesas)
fuente
schedule.js
será esclarecedor.Respuestas:
Si estamos hablando de IE puedes usar
setImmediate
https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate
setImmediate
es compatible con IE10. Entonces, más una versión de IE.Y, si está interesado, más Node.js.
Hay otros posibles polyfills, aquí hay un par de implementaciones: https://github.com/YuzuJS/setImmediate/blob/master/setImmediate.js (este se menciona en MDN) https://github.com/taylorhakes/ setAsap / blob / master / setAsap.js (uno más simple)
Y como casi todos los polyfills son feos también.
Pero de todos modos, aquí hay un ejemplo en su esencia (usando postMessage), y creo que es el menos feo de todos (pero tampoco es un verdadero polyfill)
fuente
Vi que las
mutationObserver
devoluciones de llamada usan microtask, y afortunadamente, IE11 lo admite, así que tuve la idea de poner en cola una microtask en IE11 guardando la devolución de llamada y luego disparando inmediatamente al observador cambiando un elemento:Puede abrir IE11 y ver el funcionamiento anterior, pero el código parece extraño.
fuente