vue node nexttick loop event javascript node.js setimmediate

javascript - node - setImmediate vs. nextTick



nexttick vue (6)

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.

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.


En los comentarios de la respuesta, no se establece explícitamente que nextTick pasó de Macrosemánticos a Microsemánticos.

antes del nodo 0.9 (cuando se introdujo setImmediate), nextTick operaba al inicio de la siguiente pila de llamadas.

desde el nodo 0.9, nextTick opera al final de la pila de llamadas existente, mientras que setImmediate está al comienzo de la siguiente pila de llamadas

visite https://github.com/YuzuJS/setImmediate para obtener herramientas y detalles


En términos simples, process.NextTick () se ejecutaría en el siguiente tick del ciclo de eventos. Sin embargo, el setImmediate, básicamente, tiene una fase separada que garantiza que la devolución de llamada registrada en setImmediate () se llamará solo después de la llamada de IO y la fase de sondeo.

Consulte este enlace para obtener una buena explicación: https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c


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.


Utilice setImmediate si desea poner en cola la función detrás de las devoluciones de llamada de eventos de E / S que ya están en la cola de eventos. Use process.nextTick para poner en cola la función en la cabecera de la cola de eventos, de manera que se ejecute inmediatamente después de que se complete la función actual.

Por lo tanto, en el caso de que esté intentando dividir un trabajo de larga duración, vinculado a la CPU mediante la recursión, ahora querría usar setImmediate lugar de process.nextTick setImmediate en la siguiente iteración, de lo contrario, cualquier devolución de llamadas de eventos de E / S no t tener la oportunidad de correr entre iteraciones.