93 votes

nextTick vs setImmediate, explication visuelle

Je suis très confus quant aux différences entre nextTick et setImmediate. J'ai lu toute la documentation à leur sujet sur Internet mais je ne comprends toujours pas comment ils fonctionnent.

Exemples :

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

prochainTick

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

Pourquoi ces résultats ? Veuillez expliquer avec un visuel ou une explication très facile à suivre. Même les développeurs de node core ne sont pas d'accord sur la façon dont nextTick et setImmediate doivent être compris par les gens.

Sources :

106voto

Dave Stibrany Points 890

Prenons les deux exemples suivants :

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

prochainTick

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'

Les rappels setImmediate sont déclenchés à partir de la boucle d'événement, une fois par itération dans l'ordre où ils ont été mis en file d'attente. Ainsi, à la première itération de la boucle d'événement, le callback A est déclenché. Ensuite, à la deuxième itération de la boucle d'événement, le callback B est déclenché, puis à la troisième itération de la boucle d'événement, le callback C est déclenché, etc. Cela empêche la boucle d'événement d'être bloquée et permet à d'autres callbacks d'E/S ou de temporisation d'être appelés pendant ce temps (comme c'est le cas du timeout 0ms, qui est déclenché à la 1ère ou 2ème itération de la boucle).

Les rappels nextTick, cependant, sont toujours déclenchés immédiatement après la fin de l'exécution du code actuel et AVANT de revenir à la boucle d'événements. Dans l'exemple nextTick, nous finissons par exécuter tous les callbacks nextTick avant même de revenir à la boucle d'événements. Comme le callback de setTimeout sera appelé à partir de la boucle d'événements, le texte 'TIMEOUT FIRED' ne sera pas affiché avant que nous ayons terminé tous les callbacks nextTick.

25voto

gsalgadotoledo Points 1165

Selon la documentation de Node.js, les noms de ces deux fonctions sont les suivants exactement échangés

setImmediate() ( LE MIEUX RECOMMANDÉ )

C'est le premier feu à la file d'attente des événements


process.nextTick() ( UTILISER POUR DES CAS PARTICULIERS voir l'exemple plus loin )

C'est un feu immédiat, c'est une sorte d'écriture d'une déclaration plus à la fin au fichier actuel.


Si nous avons ce code

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');

Une explication visuelle selon votre demande :

enter image description here

Cas d'utilisation de process.nextTick() lorsque vous devez émettre un événement avant de le gérer :

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!');
});

Regardez cette vidéo où Philip Roberts donnez-nous une bonne explication sur la boucle d'événement d'exécution et regardez ce débogueur de boucle d'événement en ligne Test en direct du fonctionnement de la boucle d'événement

Source : https://github.com/nodejs/node/blob/master/doc/topics/the-event-loop-timers-and-nexttick.md#processnexttick-vs-setimmediate

8voto

freakish Points 20067

Je ne peux pas reproduire vos résultats pour setImmediate . Il devrait être le même que nextTick (et c'est le cas dans mes tests) puisque dans cette situation, ils font à peu près la même chose. La seule explication raisonnable à cela est que setImmediate est en quelque sorte synchrone, mais ce n'est pas le cas.

Et selon Documentation NodeJS la seule vraie différence est que les multiples nextTick peut se déclencher au cours d'une itération de la boucle (en fonction de l'option maxTickDepth ), tandis que setImmediate se déclenche une fois par itération.

6voto

Venkat Points 632

Le tableau ci-dessous vous permet d'y voir plus clair.

setImmediate

  1. Il exécute un script une fois que la phase de sondage en cours est terminée.
  2. Il s'agit d'une fonction de module de temporisation et les fonctions de temporisation sont globales, vous pouvez les appeler sans require .
  3. Il peut être effacé par clearImmediate().
  4. Définit l'exécution "immédiate" de la callback après les callbacks des événements E/S avant setTimeout() et setInterval().

prochainTick

  1. C'est une fonction d'objet global de processus de NodeJS.
  2. Tous les callbacks passés à process.nextTick() seront résolus avant que la boucle d'événement ne continue.
  3. Permettez aux utilisateurs de gérer les erreurs.
  4. Cela permet de réessayer la demande avant que la boucle d'événements ne se poursuive.

Simple code Snippet.

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
*/

2voto

Guichi Points 365

Je pense que toutes les réponses ci-dessus sont obsolètes, parce que j'ai obtenu des réponses différentes constamment avec la version actuelle de nodejs et il est facile de raisonner sur

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

Après avoir lu https://github.com/nodejs/node/blob/master/doc/topics/the-event-loop-timers-and-nexttick.md#processnexttick-vs-setimmediate commençons par l'utilisation setImmediate nous devons garder la trace de la check queue parce que c'est là que le setImmediate le résidu du rappel.

Première itération

A est poussé vers check queue

file d'attente de vérification : [A]

Deuxième itération

A est retiré de queue d'exécuter

Pendant son exécution ,il a mis B y E a queue et ensuite, A terminer et commencer l'itération suivante

file d'attente de vérification : [B,E]

Troisième itération

se retirer B et pousser C D

file d'attente de contrôle : [E,C,D]

Quatrième itération

se retirer E et pousser F G

file de contrôle : [C,D,F,G]

Enfin

exécuter les callbacks dans la file d'attente de manière séquentielle

Pour nextTick Dans ce cas, la file d'attente fonctionne exactement de la même manière, c'est pourquoi elle produit le même résultat.

La différence est que :

le nextTickQueue sera traité après l'opération en cours est terminée, quelle que soit la phase actuelle de la boucle d'événements.

Pour être clair, la boucle d'événement maintient plusieurs files d'attente et check queue est l'une d'entre elles, le nœud décidera de la file d'attente à utiliser en fonction de certaines règles.

avec process.nextTick cependant, il contourne en quelque sorte toutes les règles et exécute le callback en nextTick immédiatement

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X