Comprender cómo el event loop decide qué ejecutar primero es fundamental para dominar la asincronía en JavaScript. No existe una sola cola de tareas: existen dos categorías con prioridades distintas que determinan el orden exacto de ejecución. Conocer esta diferencia te permitirá predecir el comportamiento de promesas, temporizadores y eventos del DOM con total claridad.
¿Qué son las macrotask y por qué se consideran tareas ordinarias?
Las macrotask son las tareas que el event loop procesa de una en una. Toma una, la ejecuta completamente y solo entonces considera la siguiente. Las cuatro macrotask principales son:
- setTimeout: ejecuta código después de un tiempo específico, por ejemplo cero segundos o dos segundos [0:55].
- setInterval: repite la ejecución en cada intervalo definido, como cada segundo [1:07].
- Eventos del DOM: cualquier interacción como dar clic, llenar un formulario o presionar un botón, por ejemplo
document.addEventListener('click', ...) [2:20].
- setImmediate: disponible en Node.js, se ejecuta después de la fase actual del event loop [2:30].
Cuando ejecutas un archivo con setTimeout y setInterval, primero aparece el resultado del timeout y luego cada segundo se imprime el intervalo [1:30]. Esto demuestra que ambas son macrotask procesadas en orden.
¿Cómo se configuran macrotask en código?
Usando Node.js puedes probar directamente estos ejemplos. Se recomienda utilizar siempre la versión LTS (long-term support) de Node.js para mayor estabilidad [1:22]. El editor de código puede ser cualquiera de tu preferencia.
¿Qué son las microtask y por qué tienen prioridad?
Las microtask funcionan como una cola prioritaria. Se generan principalmente por promesas y sus callbacks de .then(), .catch() y .finally(), además de queueMicrotask() [2:45].
Las promesas manejan tres estados: resolved, pending y rejected [3:05]. La sintaxis básica consiste en una función que se resolverá en el futuro, y al resolverse se encadena con .then() para ejecutar la lógica siguiente.
Al ejecutar dos promesas y un queueMicrotask(), el resultado es ordenado: promesa uno, promesa dos y el queue microtask [3:35]. Todas las microtask se procesan juntas antes de que cualquier macrotask tenga oportunidad de ejecutarse.
¿Cuál es la diferencia crítica entre microtask y macrotask?
La regla es clara: después de que cada macrotask termina, el event loop vacía completamente la cola de microtask antes de pasar a la siguiente macrotask [3:45]. La regla mental que debes recordar es que siempre se terminan las microtask antes de avanzar a las macrotask.
¿Qué orden sigue JavaScript cuando mezcla código síncrono, microtask y macrotask?
Cuando en un mismo archivo conviven código síncrono, un setTimeout (macrotask) y una promesa (microtask), el orden de ejecución es predecible [4:00]:
- Primero se ejecuta todo el código síncrono (como
console.log de inicio y fin).
- Luego se procesan todas las microtask (la promesa resuelta).
- Por último se ejecutan las macrotask (el
setTimeout, aunque tenga un delay de cero milisegundos).
Esto significa que incluso si el setTimeout tiene un retraso de cien milisegundos, la promesa siempre se ejecutará antes [4:30].
¿Qué sucede si una microtask genera otra microtask?
Todas se ejecutan antes de avanzar a la siguiente macrotask. El event loop no sale de la cola de microtask hasta que esté completamente vacía [4:50]. Esto es fundamental para entender cadenas de promesas encadenadas con .then().
Con este conocimiento tienes el modelo mental completo: el single thread, el call stack, el event loop y las dos colas de tareas [5:05]. Los callbacks, las promesas y async/await son construcciones que operan sobre estos cimientos. Si quieres profundizar, comparte en los comentarios qué parte del event loop te resultó más reveladora.