Skip to content

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:

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():

js
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:

js
// 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.