setTimeout () vs setImmediate () Timer en Node.js

setTimeout

Funciones setTimeout frente a setImmediate Timer en Node.js

setTimeout () vs setImmediate () – Node.js es una arquitectura asincrónica, no bloqueante y controlada por eventos. Está muy inspirado en el diseño del modelo de alta concurrencia del servidor web Nginx.

Al igual que el proceso maestro y una serie de conceptos de procesos de trabajo en Nginx, Node.js utiliza un bucle de eventos de un solo subproceso, así como un grupo de subprocesos. La biblioteca LibUV ayuda a Node.js a implementar el ciclo de eventos.

Como se muestra en la imagen a continuación, así es como se ven las diferentes fases en el bucle de eventos:

setTimeout


Introducción

Ahora que llega a la fase de ejecución del bucle de eventos, los temporizadores son una de las funciones más importantes que ayudan a programar scripts basados en tiempos de espera, así como en la ejecución inmediata. Entonces, aquí hay una publicación que cubre principalmente la ejecución de dos funciones de temporizador importantes, setTimeout () y setImmediate (), según su diseño para ejecutarse en fases separadas del bucle de eventos.

setTimeout

Ejecución “Cuando yo lo diga”: setTimeout ()

let milliSeconds = 1000;
const funcExecAfterMiliSec = () =>{
    console.log(`This line of code is executed after ${milliSeconds} milliseconds`);
}
setTimeout(funcExecAfterMiliSec, milliSeconds);

La timers phase (fase de temporizadores) en el bucle de eventos programa la ejecución de la función de devolución de llamada funcExecAfterMiliSec, especifica el umbral después del cual se puede ejecutar la devolución de llamada proporcionada. Según los documentos de Node.js,

 

Técnicamente, la poll phase (fase de encuesta) controla cuándo se ejecutan los temporizadores.

 

Ejecución “Inmediatamente después de esto”:  setImmediate ()

let immediateFunc = (args) => {
    console.log(`This line of code is executed immediately by ${args}`);
}
setImmediate(immediateFunc, 'setImmediate');

Las poll check (fases de encuesta) y check phase (fase de verificación) son responsables de la programación y ejecución de este evento de temporizador inmediato. Cuando el bucle de eventos entra en la fase de sondeo, su primera prioridad es agotar la cola de sondeo. Si la cola de sondeo está vacía, busca scripts programados por setImmediate (). Si está allí, finaliza la fase de sondeo y entra en la fase de verificación para ejecutar esos scripts. Según los documentos de Node.js,

 

setImmediate() es en realidad un temporizador especial que se ejecuta en una fase separada del ciclo de eventos. Utiliza una API libuv que programa las devoluciones de llamada para que se ejecuten una vez finalizada la fase de poll (encuesta).

 

Ahora, la pregunta es: ¿no podemos lograr el mismo comportamiento con setTimeout () de esta manera?

let milliSeconds = 0;
const funcExecAfterMiliSec = () =>{
    console.log(`This line of code is executed after ${milliSeconds} milliseconds`);
}
setTimeout(funcExecAfterMiliSec, milliSeconds);

Como aprendimos anteriormente, ambos eventos de temporizador se ejecutan en diferentes fases del ciclo de eventos. Como setImmediate () está diseñado para ejecutar un script una vez que se completa la poll phase (fase de encuesta) actual, significa que se ejecuta después de que la cola de encuesta esté vacía y el event loop (bucle de eventos) esté inactivo; mientras que la ejecución de setTimeout () está programada por la timer phase (fase del temporizador), que especifica el umbral después del cual se puede ejecutar la devolución de llamada proporcionada, dependiendo de la fase de sondeo.

Pero hay un problema aquí: intentemos ejecutar ambas funciones de temporizador en un script que no está dentro de un ciclo de E / S, lo que simplemente significa que el bucle de eventos no está ocupado en la ejecución de ninguna devolución de llamada.

const funcToExecute = (timerFunc) => {
    console.log(`Function executed by ${timerFunc}`);
}

setTimeout(() => funcToExecute('setTimeout'), 0);
setImmediate(funcToExecute, 'setImmediate');

En el script anterior, no es determinista adivinar el orden en el que se ejecutarán los dos temporizadores, ya que están sujetos a la ejecución del proceso.

const fs = require('fs');
const funcToExecute = (timer) => {
    console.log(`Function executed by ${timer}`);
}
fs.readFile(__filename, () => {
    setTimeout(() => funcToExecute('setTimeout'), 0);
    setImmediate(funcToExecute, 'setImmediate');
});

Mientras que este script le garantiza primero la ejecución de la función de temporizador setImmediate () después de que “el bucle de eventos finaliza con la ejecución del evento de lectura de archivo de la cola de eventos de E / S y la cola de eventos está vacía”. Por lo tanto, el bucle de eventos conocerá el script de devolución de llamada inmediata programado en la poll phase (fase de encuesta) y pasará a la check phase (fase de verificación) para la ejecución del mismo.

Conclusión

Aunque la ejecución del script en la cola inmediata y la cola de tiempos de espera no le mostrarán diferencias importantes en escenarios donde no hay ciclo de E / S involucrado (por lo tanto, no determinista), en los casos en que ejecutamos esas funciones de temporizador en ciclos de E / S específicos, luego vemos el significado real de su implementación diferente.

Eso es todo por este. Escribiré pronto sobre la comparación con process.nextTick () que tiene un propósito especial. Espero que hayas disfrutado leyendo esta publicación. ¡Gracias!

Recent Post