El event loop es el mecanismo que permite a Node.js ejecutar tareas asíncronas pese a ser single thread. Si trabajas con Node.js y quieres pasar a un nivel avanzado, entender sus fases es clave para escribir código eficiente y evitar bloqueos.
La idea central es simple: aunque JavaScript corre en un solo hilo, el event loop delega tareas al kernel del sistema operativo y coordina cuándo ejecutar cada callback. Esa coordinación ocurre en seis fases que se repiten en ciclo.
¿Cuáles son las fases del event loop en Node.js?
Cada vuelta del event loop pasa por seis fases en orden. Conocerlas te ayuda a predecir cuándo se ejecuta tu código.
¿Cómo funcionan los timers y los pending callbacks?
La fase de timers es la primera del ciclo y ahí se ejecutan los setTimeout y setInterval que programaste. Algo importante: el tiempo que defines es relativo, no exacto. El event loop solo verifica si el timer ya expiró; si otra fase está ocupada, tu callback puede demorar más de lo que pediste.
¿El setTimeout en Node.js se ejecuta en el tiempo exacto que indico? No. El tiempo es relativo. Node revisa si el timer ya expiró y, si el event loop está ocupado en otra fase, tu callback se ejecutará después del tiempo programado.
Luego viene pending callbacks, donde Node se comunica directamente con el kernel para detectar qué operaciones ya terminaron, como leer un archivo o una operación de red. Aquí no se ejecuta el código del callback; solo se encola para una fase posterior.
¿Qué pasa en las fases idle, prepare y poll?
La fase idle o prepare es interna de Node.js. No tienes control sobre ella desde tu código y, si no hay tareas pendientes, es donde el event loop pasa más tiempo en reposo.
Después llega poll, que es probablemente la fase más importante. Aquí ocurren tres cosas:
- Se ejecutan los callbacks que ya fueron encolados desde pending callbacks.
- Se reciben nuevas instrucciones para procesar.
- Se decide si el event loop debe bloquearse cuando hay código síncrono pendiente.
Un ejemplo claro: todo el procesamiento de strings es síncrono, así que poll es donde se bloquea el event loop para ejecutarlo. También es donde se encolan nuevos callbacks que dependerán del sistema operativo.
¿Para qué sirven check y close callbacks?
En la fase check se ejecuta lo que programaste con setImmediate. Su utilidad concreta: te permite correr código justo después de la fase de poll, lo cual es clave cuando necesitas ese orden específico.
La fase final es close callbacks, donde corren los eventos de cierre. Por ejemplo, si tienes un socket escuchando datos y se cierra, ahí se dispara el evento close. Lo mismo ocurre con streams y otras abstracciones que exponen cierre. Cuando esta fase termina, el event loop vuelve al inicio y el ciclo se repite.
¿Qué es process.nextTick y por qué usarlo con cuidado?
El método process.nextTick es un mecanismo adicional para manejar asincronía que técnicamente vive fuera del event loop. Te permite encolar microtareas que interrumpen la ejecución para correr en el momento que las necesites.
¿Qué hace process.nextTick en Node.js? Encola microtareas que se ejecutan fuera del ciclo del event loop, interrumpiendo la ejecución para correr código de forma prioritaria. Es útil, pero abusar de él puede bloquear el event loop.
Aquí viene la advertencia importante: si ejecutas demasiadas funciones con process.nextTick, puedes matar de hambre al event loop. Esto significa que el event loop pierde la capacidad de procesar lecturas de archivos, llamadas de red u otras tareas porque next tick acapara el procesamiento. Es un mecanismo que hace un poco de trampa al ciclo normal, así que úsalo solo cuando sea estrictamente necesario.
¿Qué deberías recordar sobre el event loop?
Estos son los puntos prácticos que conviene tener presentes al escribir código Node.js:
- Los tiempos de
setTimeout y setInterval son relativos, no exactos.
- La fase de poll es donde se ejecuta la mayoría de tu código asíncrono.
setImmediate corre en la fase de check, después de poll.
- Los eventos
close de sockets y streams viven en close callbacks.
process.nextTick está fuera del event loop y puede bloquearlo si abusas.
Con esta base ya entiendes cómo Node.js coordina tareas asíncronas pese a ser single thread. El siguiente paso natural es conocer LibUV, la librería que hace posible toda esta orquestación con el sistema operativo. ¿Habías notado antes el impacto de process.nextTick en tus aplicaciones? Cuéntame en los comentarios.