Ir al contenido principal
Volver al blog
13 de marzo de 20265 min de lectura

Domina el Event Loop: El Corazón de Node.js

Si programas en Node.js, seguramente has escuchado que es "single-threaded".
Nodejseventloop
Domina el Event Loop: El Corazón de Node.js

¿Cómo es que puede manejar miles de conexiones simultáneas si solo tiene un hilo? La respuesta es el Event Loop.

¿Qué es el Event Loop?

Es el mecanismo que permite a Node.js realizar operaciones de I/O no bloqueantes. Imagina un mozo en un restaurante: no se queda parado frente a la mesa esperando que el chef cocine el plato; toma el pedido, lo deja en la cocina y pasa a la siguiente mesa. Cuando el plato está listo, vuelve para entregarlo.

Las Fases Principales

El loop no es un círculo caótico, tiene un orden estricto:

  1. Timers: Se ejecutan los setTimeout y setInterval que ya expiraron.

  2. Poll (Encuesta): Aquí es donde Node busca nuevos eventos de I/O (lectura de archivos, red). Es donde pasa la mayor parte del tiempo.

  3. Check: Reservado específicamente para setImmediate.

Microtasks vs Macrotasks: La jerarquía invisible

Este es el error más común en entrevistas técnicas.

  • Macrotasks: Son los eventos del loop (timers, I/O).

  • Microtasks: Incluyen las promesas y process.nextTick().

La regla de oro: Las microtasks se ejecutan siempre al terminar la fase actual del Event Loop, antes de pasar a la siguiente macrotask. Si llenas el código de microtasks recursivas, vas a "congelar" el Event Loop porque nunca llegará a la fase de I/O.

Microtasks, Macrotasks y el orden de ejecución en Node.js

¿Alguna vez te has preguntado por qué una Promesa se ejecuta antes que un setTimeout(0)? La respuesta está en la prioridad de las colas. Vamos a verlo con un ejemplo real que podrías encontrar en una entrevista.

El Experimento de Código

Mira este bloque e intenta adivinar el orden de salida por consola:

JavaScript

console.log('1. Inicio (Síncrono)');

setTimeout(() => console.log('2. Timeout (Macrotask)'), 0);

setImmediate(() => console.log('3. Immediate (Check phase)'));

Promise.resolve().then(() => console.log('4. Promesa (Microtask)'));

process.nextTick(() => console.log('5. NextTick (Prioridad máxima)'));

console.log('6. Fin (Síncrono)');

El Resultado Explicado

  1. Síncrono primero: Se imprime 1 y 6. Todo lo síncrono bloquea el loop.

  2. Drenando Microtasks: Antes de que el loop pase a la fase de Timers, vacía las colas de microtasks:

    • process.nextTick gana: Imprime 5.

    • Promesas siguen: Imprime 4.

  3. Event Loop entra en acción:

    • Fase de Timers: Ve que el setTimeout de 0ms expiró. Imprime 2.

    • Fase de Check: Se ejecuta el setImmediate. Imprime 3.

Orden final: 1, 6, 5, 4, 2, 3.

¿Por qué importa? Si abusas de process.nextTick, puedes causar un "I/O Starvation", impidiendo que el loop llegue nunca a la fase de lectura de archivos o red.

Compartir

Comentarios

Domina el Event Loop: El Corazón de Node.js