Cuando ejecuto este código en Firefox y Chrome, los resultados son diferentes:
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();En Chrome (y Node.js), esto se imprime:
1 3 2 4En Firefox, esto se imprime:
1 2 3 4 Pero si elimino la línea 2 ( setTimeout(() => console.log("1"), 0); ), entonces se imprime lo mismo en todas las plataformas:
2 3 4¿Cómo explicar estos diferentes resultados?
¡Gracias!
Los detalles de cuándo se agregan "mensajes" diferidos a la cola de mensajes del bucle de eventos son detalles de implementación, no garantías documentadas. En el momento en que su función devuelva el control al bucle de eventos, todas sus llamadas setTimeout son elegibles para ejecutarse (tres de ellas estaban programadas para ejecutarse de inmediato, una de ellas estaba programada para ejecutarse en 100 ms) y ha garantizado que ha sido al menos 400 ms desde que lo programó.
La diferencia entre los dos podría ser tan simple como si eligen buscar tareas diferidas que estén listas (para pasar de la cola diferida a la cola de mensajes principal "lista para comenzar") inmediatamente antes o inmediatamente después de que se inserten nuevos elementos en la cola de mensajes principal. Chrome elige moverse inmediatamente después de que se programe 3 (por lo que entra 3 , luego el 2 diferido), Firefox inmediatamente antes (moviéndose en 2 antes de que ponga 3 ).
Ambos podrían cambiar en la próxima versión sin violar ninguna garantía documentada. No confíes en él, no esperes que sea estable. Si bien se garantiza que las tareas programadas de inmediato se ejecutarán en orden FIFO , no hay garantías sobre cuándo las tareas diferidas se moverán a la cola de mensajes "listos para usar" . La especificación parece requerir que 1 , 3 y 4 se ejecuten en ese orden (ya que todos estaban listos de inmediato, no diferidos), y solo el orden de 2 es flexible, pero incluso eso no es una verdadera garantía; puede volverse extraño con las diversas formas en que una tarea setTimeout "inmediata" en realidad no se puede programar de inmediato .
Puede que le interesen los documentos de MDN sobre por qué setTimeout puede tardar más de lo esperado ; explica por efecto secundario gran parte de cómo funciona el ciclo de eventos, aunque cuidadosamente no proporciona garantías sobre los detalles que está explorando.
No puedo darle una explicación completa y detallada, pero el segundo parámetro de setTimeoput y setInterval no significa que lo ejecutará exactamente en ese momento. Lo pondrán en una cola, para que el fondo pueda ejecutarlo.
El navegador tiene un ciclo de vida cuando ejecuta pasos específicos para actualizar los datos y los estilos.
Solo puedo enviarte este enlace de youtube, que me ayudó a aprender más al respecto: