javascript event loop - setImmediate vs. nextTick





3 Answers

Como una ilustracion

import fs from 'fs';
import http from 'http';

const options = {
  host: 'www.stackoverflow.com',
  port: 80,
  path: '/index.html'
};

describe('deferredExecution', () => {
  it('deferredExecution', (done) => {
    console.log('Start');
    setTimeout(() => console.log('TO1'), 0);
    setImmediate(() => console.log('IM1'));
    process.nextTick(() => console.log('NT1'));
    setImmediate(() => console.log('IM2'));
    process.nextTick(() => console.log('NT2'));
    http.get(options, () => console.log('IO1'));
    fs.readdir(process.cwd(), () => console.log('IO2'));
    setImmediate(() => console.log('IM3'));
    process.nextTick(() => console.log('NT3'));
    setImmediate(() => console.log('IM4'));
    fs.readdir(process.cwd(), () => console.log('IO3'));
    console.log('Done');
    setTimeout(done, 1500);
  });
});

dará la siguiente salida

Start
Done
NT1
NT2
NT3
TO1
IO2
IO3
IM1
IM2
IM3
IM4
IO1

Espero que esto pueda ayudar a entender la diferencia.

node js vue

La versión 0.10 de Node.js se lanzó hoy y presentó setImmediate . La documentación de cambios de API sugiere su uso al hacer llamadas nextTick recursivas.

Por lo que dice MDN , parece muy similar a process.nextTick .

¿Cuándo debo usar nextTick y cuándo debo usar setImmediate ?




Creo que puedo ilustrar esto muy bien. Dado que se llama a nextTick al final de la operación actual, llamarla recursivamente puede terminar impidiendo que el bucle de eventos continúe. setImmediate resuelve esto setImmediate la fase de verificación del bucle de eventos, permitiendo que el ciclo de eventos continúe normalmente.

   ┌───────────────────────┐
┌─>│        timers         │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     I/O callbacks     │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     idle, prepare     │
│  └──────────┬────────────┘      ┌───────────────┐
│  ┌──────────┴────────────┐      │   incoming:   │
│  │         poll          │<─────┤  connections, │
│  └──────────┬────────────┘      │   data, etc.  │
│  ┌──────────┴────────────┐      └───────────────┘
│  │        check          │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
└──┤    close callbacks    │
   └───────────────────────┘

fuente: nodejs.org/en/docs/guides/event-loop-timers-and-nexttick

Observe que la fase de verificación se encuentra inmediatamente después de la fase de sondeo. Esto se debe a que la fase de sondeo y las devoluciones de llamada de E / S son los lugares más probables en los que se setImmediate llamadas a setImmediate . Por lo tanto, lo ideal sería que la mayoría de esas llamadas sean bastante inmediatas, pero no tan inmediatas como nextTick que se comprueba después de cada operación y técnicamente existe fuera del bucle de eventos.

Veamos un pequeño ejemplo de la diferencia entre setImmediate y process.nextTick :

function step(iteration) {
  if (iteration === 10) return;
  setImmediate(() => {
    console.log(`setImmediate iteration: ${iteration}`);
    step(iteration + 1); // Recursive call from setImmediate handler.
  });
  process.nextTick(() => {
    console.log(`nextTick iteration: ${iteration}`);
  });
}
step(0);

Digamos que acabamos de ejecutar este programa y estamos pasando por la primera iteración del bucle de eventos. Llamará a la función de step con iteración cero. Luego registrará dos manejadores, uno para setImmediate y otro para process.nextTick . Luego, setImmediate esta función recursivamente desde el controlador setImmediate que se ejecutará en la siguiente fase de verificación. El controlador nextTick se ejecutará al final de la operación actual, interrumpiendo el bucle de eventos, por lo que, aunque se haya registrado en segundo lugar, se ejecutará primero.

El orden finaliza: nextTick dispara a medida que finaliza la operación actual, comienza el siguiente ciclo de eventos, se ejecutan las fases normales de los eventos, setImmediate dispara y recursivamente llama a nuestra función de step para iniciar el proceso nuevamente. Finaliza la operación actual, se dispara nextTick , etc.

La salida del código anterior sería:

nextTick iteration: 0
setImmediate iteration: 0
nextTick iteration: 1
setImmediate iteration: 1
nextTick iteration: 2
setImmediate iteration: 2
nextTick iteration: 3
setImmediate iteration: 3
nextTick iteration: 4
setImmediate iteration: 4
nextTick iteration: 5
setImmediate iteration: 5
nextTick iteration: 6
setImmediate iteration: 6
nextTick iteration: 7
setImmediate iteration: 7
nextTick iteration: 8
setImmediate iteration: 8
nextTick iteration: 9
setImmediate iteration: 9

Ahora movamos nuestra llamada recursiva para step a nuestro controlador nextTick lugar de setImmediate .

function step(iteration) {
  if (iteration === 10) return;
  setImmediate(() => {
    console.log(`setImmediate iteration: ${iteration}`);
  });
  process.nextTick(() => {
    console.log(`nextTick iteration: ${iteration}`);
    step(iteration + 1); // Recursive call from nextTick handler.
  });
}
step(0);

Ahora que hemos movido la llamada recursiva para step al controlador de nextTick cosas se comportarán en un orden diferente. Nuestra primera iteración del bucle de eventos se ejecuta y llama step registrando un controlador setImmedaite así como un controlador nextTick . Una vez que finaliza la operación actual, nuestro controlador nextTick que recursivamente llama a step y registra otro controlador setImmediate , así como otro controlador nextTick . Dado que el controlador nextTick después de la operación actual, el registro de un controlador nextTick dentro de un controlador nextTick hará que el segundo controlador se ejecute inmediatamente después de que finalice la operación actual del controlador. Los controladores nextTick continuarán nextTick , evitando que el bucle de eventos actual continúe. nextTick todos los controladores de nextTick antes de ver que se setImmediate un solo controlador setImmediate .

La salida del código anterior termina siendo:

nextTick iteration: 0
nextTick iteration: 1
nextTick iteration: 2
nextTick iteration: 3
nextTick iteration: 4
nextTick iteration: 5
nextTick iteration: 6
nextTick iteration: 7
nextTick iteration: 8
nextTick iteration: 9
setImmediate iteration: 0
setImmediate iteration: 1
setImmediate iteration: 2
setImmediate iteration: 3
setImmediate iteration: 4
setImmediate iteration: 5
setImmediate iteration: 6
setImmediate iteration: 7
setImmediate iteration: 8
setImmediate iteration: 9

Tenga en cuenta que si no hubiéramos interrumpido la llamada recursiva y la nextTick cancelado después de 10 iteraciones, las llamadas nextTick seguirían siendo recurrentes y nunca permitirían que el bucle de eventos continúe a la siguiente fase. Así es como nextTick puede convertirse en bloqueo cuando se usa recursivamente, mientras que setImmediate se setImmediate en el próximo bucle de eventos y establecer otro controlador setImmediate desde uno no interrumpirá el bucle de eventos actual, lo que le permite continuar ejecutando las fases del bucle de eventos como normal .

¡Espero que ayude!

PD: estoy de acuerdo con otros comentaristas en que los nombres de las dos funciones podrían intercambiarse fácilmente, ya que suena nextTick parece que se nextTick en el próximo bucle de eventos en lugar del final del actual, y el final del bucle actual es más " inmediato "que el comienzo del siguiente bucle. Bueno, eso es lo que obtenemos a medida que la API madura y la gente depende de las interfaces existentes.




Le recomiendo que consulte la sección de nodejs.org/en/docs/guides/event-loop-timers-and-nexttick dedicada a Loop para obtener una mejor comprensión. Algunos fragmentos tomados de allí:

Tenemos dos llamadas que son similares en lo que concierne a los usuarios, pero sus nombres son confusos.

  • process.nextTick () se dispara inmediatamente en la misma fase

  • setImmediate () se activa en la siguiente iteración o 'tick' de la
    bucle de eventos

En esencia, los nombres deben ser intercambiados. process.nextTick () se dispara más inmediatamente que setImmediate (), pero este es un artefacto del pasado que es poco probable que cambie.




Related