Estoy muy confundido acerca de las diferencias entre nextTick y setImmediate. He leído toda la documentación sobre ellos en Internet pero todavía no entiendo cómo funcionan.
Ejemplos:
function log(n) { console.log(n); }
setImmediate
setImmediate(function() {
setImmediate(function() {
log(1);
setImmediate(function() { log(2); });
setImmediate(function() { log(3); });
});
setImmediate(function() {
log(4);
setImmediate(function() { log(5); });
setImmediate(function() { log(6); });
});
});
//1 2 3 4 5 6
nextTick
process.nextTick(function() {
process.nextTick(function() {
log(1);
process.nextTick(function() { log(2); });
process.nextTick(function() { log(3); });
});
process.nextTick(function() {
log(4);
process.nextTick(function() { log(5); });
process.nextTick(function() { log(6); });
});
});
//1 4 2 3 5 6
¿Por qué estos resultados? Explique con una explicación visual o muy fácil de seguir. Incluso los desarrolladores del núcleo del nodo no están de acuerdo en cómo las personas deben entender nextTick y setImmediate.
Fuentes:
1 4 2 3 5 6
) para ambas ejecuciones (Nodo v5.6.0)Respuestas:
Considere los siguientes dos ejemplos:
setImmediate
setImmediate(function A() { setImmediate(function B() { log(1); setImmediate(function D() { log(2); }); setImmediate(function E() { log(3); }); }); setImmediate(function C() { log(4); setImmediate(function F() { log(5); }); setImmediate(function G() { log(6); }); }); }); setTimeout(function timeout() { console.log('TIMEOUT FIRED'); }, 0) // 'TIMEOUT FIRED' 1 4 2 3 5 6 // OR // 1 'TIMEOUT FIRED' 4 2 3 5 6
nextTick
process.nextTick(function A() { process.nextTick(function B() { log(1); process.nextTick(function D() { log(2); }); process.nextTick(function E() { log(3); }); }); process.nextTick(function C() { log(4); process.nextTick(function F() { log(5); }); process.nextTick(function G() { log(6); }); }); }); setTimeout(function timeout() { console.log('TIMEOUT FIRED'); }, 0) // 1 4 2 3 5 6 'TIMEOUT FIRED'
Las devoluciones de llamada setImmediate se disparan desde el bucle de eventos, una vez por iteración en el orden en que se pusieron en cola. Entonces, en la primera iteración del bucle de eventos, se activa la devolución de llamada A. Luego, en la segunda iteración del bucle de eventos, se dispara la devolución de llamada B, luego, en la tercera iteración del bucle de eventos, se dispara la devolución de llamada C, etc. Esto evita que el bucle de eventos se bloquee y permite que se realicen otras E / S o devoluciones de llamada del temporizador. llamado en el tiempo medio (como es el caso del tiempo de espera de 0ms, que se activa en la primera o segunda iteración del ciclo).
Las devoluciones de llamada de nextTick, sin embargo, siempre se disparan inmediatamente después de que el código actual termine de ejecutarse y ANTES de volver al bucle de eventos. En el ejemplo de nextTick, terminamos ejecutando todas las devoluciones de llamada de nextTick antes de volver al bucle de eventos. Dado que la devolución de llamada de setTimeout se llamará desde el bucle de eventos, el texto 'TIMEOUT FIRED' no se emitirá hasta que terminemos con cada devolución de llamada nextTick.
fuente
TIMEOUT FIRED 1 4 2 3 5 6
De acuerdo con el documento de Node.js, los nombres de estas dos funciones se intercambian exactamente
setImmediate () ( MEJOR RECOMENDADO )
Es el fuego primero en la cola de eventos
process.nextTick () ( USAR PARA CASOS ESPECIALES, ver ejemplo más adelante )
Se dispara de inmediato, es como escribir una declaración más al final del archivo actual
Si tenemos este código
setTimeout(function(){ console.log('Hello world 5'); // It's waiting like a normal person at a queue }, 0); setImmediate(function(){ console.log('Hello world 4'); // It's like get to last and be take care of first // but always after of .nextTick and before of setInterval(, 0) }); process.nextTick(function(){ console.log('Hello world 3'); // It's like be at the bottom at this file }); console.log('Hello world 1'); console.log('Hello world 2');
Una explicación visual según su solicitud:
Casos de uso process.nextTick () cuando tienes que emitir un evento antes de manejarlo:
const EventEmitter = require('events'); const util = require('util'); function MyEmitter() { EventEmitter.call(this); // use nextTick to emit the event once a handler is assigned process.nextTick(function () { this.emit('event'); }.bind(this)); } util.inherits(MyEmitter, EventEmitter); const myEmitter = new MyEmitter(); myEmitter.on('event', function() { console.log('an event occurred!'); });
Mire este video donde Philip Roberts nos da una gran explicación sobre el bucle de eventos en tiempo de ejecución y mire este depurador de eventos en línea Pruebe en vivo cómo funciona el bucle de eventos
Fuente: https://github.com/nodejs/node/blob/master/doc/topics/the-event-loop-timers-and-nexttick.md#processnexttick-vs-setimmediate
fuente
No puedo reproducir tus resultados para
setImmediate
. Debería ser lo mismo quenextTick
(y está en mis pruebas) ya que en esta situación hacen prácticamente lo mismo. La única explicación razonable para eso es que desetImmediate
alguna manera es sincrónico, pero no lo es.Y de acuerdo con la documentación de NodeJS, la única diferencia real es que varios
nextTick
pueden dispararse en una iteración de bucle (dependiendo demaxTickDepth
), mientras que sesetImmediate
dispara una vez por iteración.fuente
A continuación, obtendrá una mayor claridad.
setImmediate
require
.nextTick
Fragmento de código simple.
console.log("I'm First"); setImmediate(function () { console.log('Im setImmediate'); }); console.log("I'm Second"); process.nextTick(function () { console.log('Im nextTick'); }); console.log("I'm Last"); /* Output $ node server.js I'm First I'm Second I'm Last Im nextTick Im setImmediate */
fuente
Creo que todas las respuestas anteriores son obsoletas, porque obtuve diferentes respuestas constantemente con la versión actual de nodejs y es fácil razonar sobre
var log=console.log log(process.version) var makeAsyncCall if(false) makeAsyncCall=setImmediate else makeAsyncCall=process.nextTick; makeAsyncCall(function A () { makeAsyncCall(function B() { log(1); makeAsyncCall(function C() { log(2); }); makeAsyncCall(function D() { log(3); }); }); makeAsyncCall(function E() { log(4); makeAsyncCall(function F() { log(5); }); makeAsyncCall(function G() { log(6); }); }); }); //1 //4 //2 //3 //5 //6 //in both case
Después de leer https://github.com/nodejs/node/blob/master/doc/topics/the-event-loop-timers-and-nexttick.md#processnexttick-vs-setimmediate deje que el uso comience desde
setImmediate
debemos realizar un seguimiento de elcheck queue
ya que es donde elsetImmediate
reside devolución de llamada.Primera iteración
A
es empujar acheck queue
cola de comprobación: [A]
Segunda iteración
A
se sacaqueue
para ejecutarDurante su ejecución, puso
B
yE
toqueue
y luego,A
completó e inició la siguiente iteracióncola de comprobación: [B, E]
Tercera iteración
sacar
B
y empujarC
D
cola de comprobación: [E, C, D]
Cuarta iteración
sacar
E
y empujarF
G
cola de comprobación: [C, D, F, G]
Finalmente
ejecutar las devoluciones de llamada en la cola secuencialmente
Por
nextTick
caso, la cola funciona exactamente de la misma manera, por eso produce el mismo resultadoLo diferente es que:
Para ser claros, el bucle de eventos mantiene múltiples colas y
check queue
es solo una de ellas, el nodo decidirá qué cola usar en función de algunas reglascon
process.nextTick
sin embargo, es una especie de pasar por toda la normativa y ejecutar la devolución de llamada denextTick
forma inmediatafuente