Bucle de eventos de Javascript – ¿Por qué los manipuladores de eventos de Javascript funcionan de manera diferente?
Por favor, echa un vistazo al código a continuación:
const btn = document.createElement('button');
btn.innerText = 'botón';
document.body.appendChild(btn);
btn.addEventListener('click', () => {
setTimeout(() => {
console.log('paso1');
},0);
Promise.resolve().then(() => {
console.log('paso2');
});
});
btn.addEventListener('click', () => {
setTimeout(() => {
console.log('paso3');
},0);
Promise.resolve().then(() => {
console.log('paso4');
});
});
Cuando hago clic en el elemento botón, veo lo que esperaba a continuación:
“paso2”
“paso1”
“paso4”
“paso3”
Pero el resultado en la consola es diferente a continuación:
“paso2”
“paso4”
“paso1”
“paso3”
No entiendo por qué ocurre esto. Por favor, dame alguna respuesta.
davy.ai
Este comportamiento ocurre debido al bucle de eventos y al orden en que se ejecutan ciertas tareas.
Cuando se hace clic en el botón, se activan dos listeners de eventos simultáneamente. Cada listener de evento configura un setTimeout y un Promise.resolve para registrar mensajes en la consola.
Dado que el setTimeout está configurado para 0ms, se agrega inmediatamente a la cola de callback y espera a que se complete el código síncrono que se está ejecutando actualmente antes de poder ejecutarse. Mientras tanto, el Promise.resolve se agrega a la cola de microtareas ya que tiene una prioridad más alta que la cola de callback.
En este escenario, el Promise.resolve se ejecuta antes de que el callback de setTimeout debido a que las microtareas tienen una prioridad más alta que las macrotareas. Por lo tanto, “step2” y “step4” se imprimen primero porque se agregaron a la cola de microtareas antes de que se agregaran los callbacks de setTimeout a la cola de callback.
“Step1” se imprime antes que “step3” porque “step1” se agregó a la cola de callback antes que “step3”. Sin embargo, dado que “step1” está dentro de un setTimeout, espera a que todo el código síncrono se complete antes de que se ejecute, incluyendo el Promise.resolve que imprime “step2” y “step4”. Por lo tanto, “step3” se imprime al final.
En resumen, este comportamiento se debe al bucle de eventos y al orden en que se priorizan y ejecutan las tareas.