Fases de libuv
El bucle de eventos de libuv ejecuta fases en un orden fijo en cada "tick"; conocer la secuencia explica la deriva de los temporizadores, el comportamiento de setImmediate y cuándo se disparan las devoluciones de llamada de E/S.
Busca en todas las páginas de la documentación
El bucle de eventos de libuv ejecuta fases en un orden fijo en cada "tick"; conocer la secuencia explica la deriva de los temporizadores, el comportamiento de setImmediate y cuándo se disparan las devoluciones de llamada de E/S.
Orden de las fases (una iteración del bucle):
temporizadores → pendientes → inactivo/preparar → sondeo → verificar → devoluciones de llamada de cierre
↑ microtareas se vacían entre fases ↑
import { setTimeout, setImmediate } from 'node:timers';
setTimeout(() => console.log('timer'), 0);
setImmediate(() => console.log('immediate'));Cuándo usarlo:
setImmediate vs setTimeout(0)data de un socket en relación con los temporizadoresimport { readFile } from 'node:fs';
import { setTimeout, setImmediate } from 'node:timers';
readFile(__filename, () => {
console.log('1: I/O callback (poll phase)');
setTimeout(() => console.log('2: timer'), 0);
setImmediate(() => console.log('3: immediate (check phase)'));
});
setTimeout(() => console.log('4: outer timer'), 0);
setImmediate(() => console.log('5: outer immediate'));Patrón de salida típico:
readFile: 1, luego 3 (inmediato), luego 2 (temporizador).Lo que esto demuestra:
setImmediate en una devolución de llamada de E/S se ejecuta en la fase de verificación de la misma iteraciónsetTimeout, setInterval).setImmediate.close (por ejemplo, socket.on('close')).| Fase | Ejemplos de API | Notas |
|---|---|---|
| temporizadores | setTimeout, setInterval | Retraso mínimo, no exacto bajo carga |
| sondeo | fs.readFile, socket.on('data') | Puede bloquearse si no hay otro trabajo programado |
| verificación | setImmediate | Se ejecuta después del sondeo en el mismo tick |
| cierre | server.close, limpieza de manejadores | Última oportunidad para la eliminación de recursos |
import { setImmediate } from 'node:timers';
// Aplazar el trabajo hasta después de las devoluciones de llamada de E/S en este tick
function deferAfterIo(fn: () => void): void {
setImmediate(fn);
}setTimeout(fn, 100) se dispara exactamente a los 100ms - las fases y la carga añaden deriva. Solución: usa relojes monotónicos para los plazos, no solo el recuento del temporizador.setImmediate - la fase de verificación nunca cede a la E/S. Solución: usa setImmediate una vez por elemento, agrupa el trabajo o usa workers.| Alternativa | Cuándo usar | Cuándo NO usar |
|---|---|---|
queueMicrotask | Ejecutar antes de la siguiente macrotarea, después de la pila actual | Necesitas esperar a que termine el sondeo de E/S |
setImmediate | Aplazar después de la fase de sondeo actual | Se requiere precisión de tiempo sub-milisegundo |
setTimeout | Programación basada en tiempo con tolerancia | Programación exacta bajo carga pesada de CPU |
| Mensaje de hilo de worker | Trabajo de CPU fuera del hilo principal | Aplazamiento simple de unas pocas líneas |
Un ciclo completo a través de temporizadores, pendientes, inactivo/preparar, sondeo, verificar y cerrar, con las microtareas vaciadas entre fases.
En la fase de verificación, inmediatamente después de que la fase de sondeo se complete en esa iteración.
Los temporizadores se disparan solo cuando el bucle llega a la fase de temporizadores. El trabajo síncrono de bloqueo o el sondeo saturado retrasan esa fase.
El manejador data del socket en la fase de sondeo, luego las microtareas de cualquier Promise que cree, luego los inmediatos de la fase de verificación.
Puede esperar E/S con un tiempo de espera calculado. Si los temporizadores o los inmediatos están pendientes, se agota el tiempo y continúa.
nextTick no es una fase de libuv; se ejecuta entre fases y antes de las microtareas de Promise. El uso excesivo priva de recursos a la E/S.
Al desmontar servidores y sockets, las devoluciones de llamada close liberan los manejadores. Importante para un apagado elegante.
No, libuv siempre recorre el ciclo. Tú influyes en qué devoluciones de llamada se ponen en cola para cada fase.
Ideas similares de microtareas/macrotareas; Node añade setImmediate, process.nextTick y una integración de E/S diferente a través de libuv.
NODE_DEBUG=timer rastrea las inserciones y disparos de temporizadores; útil localmente, ruidoso en producción.
Sí, las devoluciones de llamada de finalización de E/S de red se programan a través de libuv como node:http.
Cada await del middleware produce microtareas; el envío de la respuesta activa la E/S en el sondeo. Un middleware síncrono largo bloquea todas las fases.
Versiones de la pila: Esta página fue escrita para Node.js 24.18.0 (LTS activa), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 y NestJS 11.
Revisado por Chris St. John·Última actualización: 16 jul 2026