Entendiendo setImmediate()
Cuando se desea ejecutar un fragmento de código de forma asíncrona, pero lo antes posible, una opción es usar la función setImmediate()
proporcionada por Node.js:
setImmediate(() => {
// hacer algo
})
Cualquier función pasada como argumento a setImmediate()
es una devolución de llamada que se ejecuta en la siguiente iteración del bucle de eventos.
¿En qué se diferencia setImmediate()
de setTimeout(() => {}, 0)
(pasando un tiempo de espera de 0 ms), y de process.nextTick()
y Promise.then()
?
Una función pasada a process.nextTick()
se ejecutará en la iteración actual del bucle de eventos, después de que termine la operación actual. Esto significa que siempre se ejecutará antes que setTimeout
y setImmediate
.
Una devolución de llamada setTimeout()
con un retraso de 0 ms es muy similar a setImmediate()
. El orden de ejecución dependerá de varios factores, pero ambos se ejecutarán en la siguiente iteración del bucle de eventos.
Una devolución de llamada process.nextTick
se agrega a la cola process.nextTick. Una devolución de llamada Promise.then()
se agrega a la cola de microtareas de las promesas. Una devolución de llamada setTimeout
, setImmediate
se agrega a la cola de macrotasks.
El bucle de eventos ejecuta las tareas en la cola process.nextTick primero, luego ejecuta la cola de microtareas de promesas, y luego ejecuta la cola de macrotasks setTimeout
o setImmediate
.
Aquí hay un ejemplo para mostrar el orden entre setImmediate()
, process.nextTick()
y Promise.then()
:
const baz = () => console.log('baz');
const foo = () => console.log('foo');
const zoo = () => console.log('zoo');
const start = () => {
console.log('start');
setImmediate(baz);
new Promise((resolve, reject) => {
resolve('bar');
}).then(resolve => {
console.log(resolve);
process.nextTick(zoo);
});
process.nextTick(foo);
};
start();
// start foo bar zoo baz
Este código primero llamará a start()
, luego llamará a foo()
en la cola process.nextTick. Después de eso, manejará la cola de microtareas de promesas, que imprime bar y agrega zoo()
en la cola process.nextTick al mismo tiempo. Luego llamará a zoo()
que acaba de ser agregado. Al final, se llama a baz()
en la cola de macrotasks.
El principio mencionado anteriormente es válido en los casos de CommonJS, pero tenga en cuenta que en los módulos ES, por ejemplo, archivos .mjs
, el orden de ejecución será diferente:
// start bar foo zoo baz
Esto se debe a que el módulo ES que se carga se encapsula como una operación asíncrona, y por lo tanto todo el script ya está en la cola de microtareas de promesas. Entonces, cuando la promesa se resuelve inmediatamente, su devolución de llamada se agrega a la cola de microtareas. Node.js intentará limpiar la cola hasta que se mueva a cualquier otra cola, y por lo tanto verá que imprime bar primero.