NextTick बनाम setImmediate, visual स्पष्टीकरण


90

मैं nextTick और setImmediate के बीच अंतर के बारे में बहुत उलझन में हूँ। मैंने इंटरनेट पर उनके बारे में सभी दस्तावेज पढ़े हैं लेकिन मुझे अभी भी समझ नहीं आया कि वे कैसे काम करते हैं।

उदाहरण:

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

ये नतीजे क्यों? कृपया एक दृश्य के साथ समझाएं या स्पष्टीकरण का पालन करना बहुत आसान है। यहां तक ​​कि नोड कोर देवता इस बात पर सहमत नहीं होते हैं कि लोगों को कैसे समझना चाहिए

सूत्रों का कहना है:


8
बड़ा सवाल है। मतभेदों को स्पष्ट करने का यह एक उत्कृष्ट तरीका है।
SystemParadox

8
आउटपुट 1 4 2 3 5 6दोनों निष्पादन के लिए समान ( ) है (नोड v5.6.0)
डेनिज़ ओजर

समझदार और मददगार सवाल!
मेहदी राश

दोनों एक ही आउटपुट
मेककोड

1
5 साल पहले का साल देखिए! बहुत सी चीजें बदल सकती थीं।
गेब्रियल लामास

जवाबों:


105

निम्नलिखित दो उदाहरणों पर विचार करें:

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'

setImmediate callbacks को इवेंट लूप से निकाल दिया जाता है, एक बार पुनरावृत्ति के क्रम में कि वे कतार में थे। तो इवेंट लूप के पहले पुनरावृत्ति पर, कॉलबैक ए को निकाल दिया जाता है। फिर ईवेंट लूप के दूसरे पुनरावृत्ति पर, कॉलबैक बी को निकाल दिया जाता है, फिर ईवेंट लूप कॉलबैक सी के तीसरे पुनरावृत्ति पर निकाल दिया जाता है, आदि। यह ईवेंट लूप को अवरुद्ध होने से रोकता है और अन्य I / O या टाइमर कॉलबैक की अनुमति देता है माध्य समय में कहा जाता है (जैसा कि 0ms टाइमआउट का मामला है, जिसे 1 या 2 लूप पुनरावृत्ति पर निकाल दिया जाता है)।

अगली कॉलबैक, हालांकि, वर्तमान कोड को निष्पादित करने और घटना लूप में वापस जाने के तुरंत बाद हमेशा निकाल दिया जाता है। अगली बार उदाहरण में, हम कभी भी इवेंट लूप में वापस आने से पहले सभी अगली कॉलबैक को निष्पादित करते हैं। चूंकि सेट टाइमआउट के कॉलबैक को ईवेंट लूप से बुलाया जाएगा, इसलिए टेक्स्ट 'टाइमटाइम एफआईआरईडी' तब तक आउटपुट नहीं होगा, जब तक कि हम हर नेक्स्ट कॉलबैक के साथ काम न करें।


8
सही, अंतिम पैराग्राफ मुख्य अंतर को समझने की कुंजी है।
गेब्रियल ललामास

आपके अगले उदाहरण में अलग आउटपुट है:TIMEOUT FIRED 1 4 2 3 5 6
Jürgen पॉल

आप नोड का कौन सा संस्करण चला रहे हैं? नोड 0.10 पर। ईवेंट लूप से टकराने से पहले आपको हमेशा अपना अगला कॉलबैक चलना चाहिए।
डेव स्टेब्रानी

23
काश उन्होंने एक अलग नाम चुना होता। अभी "nextTick" setImmediate की तुलना में अधिक तत्काल है।
21

1
@StrugglingCoder जब A निष्पादित करता है, तो यह B और C को अगले शेड्यूल करने के लिए सेट करता है। जब बी निष्पादित करता है तो यह निर्धारित करता है कि डी और ई को अगले शेड्यूल किया जाना है, लेकिन बी के लिए सी पहले से ही निर्धारित किया गया है। याद रखें कि कॉलबैक शेड्यूल या पंजीकृत होने और कॉलबैक वास्तव में आग लगने के बीच अंतर होता है।
डेव स्टेब्रानी

25

Node.js के अनुसार, इन दोनों फ़ंक्शन के डॉक्टर नाम बिल्कुल अदला-बदली वाले हैं

setImmediate () ( BEST अनुशंसित )

यह घटना कतार में सबसे पहले आग है


process.nextTick () ( विशेष मामलों के लिए उपयोग बाद में उदाहरण देखें )

यह तुरंत आग है, यह थोड़े वर्तमान फ़ाइल में अंत में एक बयान अधिक लिखना है


अगर हमारे पास यह कोड है

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

आपके अनुरोध के अनुसार एक दृश्य विवरण:

यहाँ छवि विवरण दर्ज करें

उपयोग की प्रक्रिया के लिए मामले ।nextTick () जब आपको इसे संभालना है और इससे पहले कि घटना है:

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

इस विडिओ को देखें जहाँ फिलिप रॉबर्ट्स ने हमें रनटाइम ईवेंट लूप के बारे में एक बेहतरीन विवरण दिया है और इस ऑनलाइन ईवेंटलूप डीबगर को देखें लाइव टेस्ट कि ईवेंट लूप कैसे काम करता है

स्रोत: https://github.com/nodejs/node/blob/master/doc/topics/the-event-loop-timers-and-nexttick.md#processnexttick-vat-setimmediate


1
यह उत्तर अधिक समझ में आता है! थैंक्स @gsalgadotoledo: p man, यह आपके नाम लिखने से भी कठिन था, अगली बार और सेट करें।
अनिल खान

8

मैं आपके परिणामों को पुन: पेश नहीं कर सकता setImmediate। यह उसी तरह होना चाहिए nextTick(और यह मेरे परीक्षणों में है) क्योंकि इस स्थिति में वे एक ही काम करते हैं। उसके लिए केवल उचित स्पष्टीकरण यह है कि setImmediateकिसी तरह समकालिक हो, लेकिन ऐसा नहीं है।

और NodeJS प्रलेखन के अनुसार एकमात्र वास्तविक अंतर यह है कि एकाधिक nextTickएक लूप पुनरावृत्ति ( आग पर निर्भर करता है maxTickDepth) में आग लग सकती है , जबकि setImmediateप्रति बार एक बार आग लगती है।


3

नीचे आपको बेहतर स्पष्टता प्रदान करता है।

setImmediate

  1. वर्तमान पोल पूरा होने के बाद यह एक स्क्रिप्ट निष्पादित करता है।
  2. यह एक टाइमर मॉड्यूल फ़ंक्शन है और टाइमर फ़ंक्शन वैश्विक हैं, आप उन्हें बिना कॉल कर सकते हैं require
  3. यह ClearImmediate () द्वारा क्लियर किया जा सकता है।
  4. SetTimeout () और setInterval () से पहले I / O ईवेंट्स कॉलबैक के बाद कॉलबैक का "तत्काल" निष्पादन सेट करें।

nextTick

  1. यह NodeJS का एक प्रोसेस ग्लोबल ऑब्जेक्ट फंक्शन है।
  2. ईवेंट लूप जारी रहने से पहले सभी कॉलबैक प्रोसेस.nextTick () में हल हो जाएंगे।
  3. उपयोगकर्ताओं को त्रुटियों को संभालने की अनुमति दें।
  4. ईवेंट लूप जारी रखने से पहले अनुरोध को फिर से आज़माने में मदद करता है।

सरल कोड स्निपेट।

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

2

मुझे लगता है कि उपरोक्त सभी उत्तर अप्रचलित हैं, क्योंकि मुझे नोडज के वर्तमान संस्करण के साथ लगातार अलग-अलग उत्तर मिले हैं और इसके बारे में तर्क करना आसान है

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

पढ़ने के बाद https://github.com/nodejs/node/blob/master/doc/topics/the-event-loop-timers-and-nexttick.md#processnexttick-vs-setimmediate उपयोग शुरू करते हैं से setImmediateहम का ट्रैक रखने चाहिए check queueक्योंकि यह जहां है setImmediateकॉलबैक रहते हैं।

पहला पुनरावृति

A को धक्का दिया है check queue

जाँच कतार: [A]

दूसरा पुनरावृति

Aqueueनिष्पादित करने के लिए बाहर खींच रहा है

इसके निष्पादन के दौरान, यह डाल Bऔर Eकरने के लिए queueऔर उसके बाद, Aपूर्ण और अगले चरण शुरू

चेक कतार: [बी, ई]

तीसरा पुनरावृति

बाहर खींचो Bऔर धक्काC D

चेक कतार: [ई, सी, डी]

फोर्थ पुनरावृत्ति

बाहर खींचो Eऔर धक्काF G

चेक कतार: [C, D, F, G]

आखिरकार

क्रमिक रूप से कतार में कॉलबैक निष्पादित करें

के लिए nextTickमामला है, कतार ठीक उसी तरह काम करता है, यही वजह है कि यह एक ही परिणाम का उत्पादन

अलग यह है कि:

अगली लूपक्व्यू को वर्तमान ऑपरेशन पूरा होने के बाद संसाधित किया जाएगा, भले ही इवेंट लूप के वर्तमान चरण की परवाह किए बिना

स्पष्ट होने के लिए, ईवेंट लूप कई कतार बनाए रखता है और check queue उनमें से सिर्फ एक है, नोड यह तय करेगा कि कुछ नियमों के आधार पर कौन सी कतार का उपयोग करना है

साथ process.nextTickतथापि, यह तरह सभी नियम को दरकिनार करने का है और में कॉलबैक पर अमल nextTickतुरंत

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.