मुझे लगता है कि मैं इसे काफी अच्छी तरह से समझा सकता हूं। चूंकि nextTick
वर्तमान ऑपरेशन के अंत में कॉल किया जाता है, इसलिए इसे पुनरावर्ती रूप से कॉल करना इवेंट लूप को जारी रखने से रोक सकता है। setImmediate
इवेंट लूप के चेक चरण में फायरिंग करके इसे हल करता है, जिससे ईवेंट लूप को सामान्य रूप से जारी रखा जा सकता है।
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
स्रोत: https://nodejs.org/en/docs/guides/event-loop-timers-and-nextroick/
ध्यान दें कि चेक चरण मतदान चरण के तुरंत बाद है। ऐसा इसलिए है क्योंकि चुनाव चरण और I / O कॉलबैक आपके कॉल setImmediate
चलने की सबसे अधिक संभावना वाले स्थान हैं । तो आदर्श रूप से उन कॉलों में से अधिकांश वास्तव में बहुत तत्काल होंगे, बस उतने ही तत्काल नहीं, nextTick
जो हर ऑपरेशन के बाद जांचे जाते हैं और तकनीकी रूप से इवेंट लूप के बाहर मौजूद होते हैं।
के बीच का अंतर का एक छोटा उदाहरण पर एक नज़र डालते हैं setImmediate
और 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);
मान लें कि हमने अभी यह कार्यक्रम चलाया है और इवेंट लूप के पहले पुनरावृत्ति के माध्यम से आगे बढ़ रहे हैं। यह step
फ़ंक्शन में पुनरावृत्ति शून्य के साथ कॉल करेगा । यह तब दो हैंडलर, एक के लिए setImmediate
और एक के लिए पंजीकृत करेगा process.nextTick
। हम फिर से इस फ़ंक्शन को setImmediate
हैंडलर से कॉल करते हैं जो अगले चेक चरण में चलेगा। nextTick
हैंडलर वर्तमान कार्रवाई घटना पाश में दखल के अंत में चला जाएगा, तो भले ही यह दूसरा पंजीकृत किया गया था यह वास्तव में पहले चलेंगे।
यह आदेश समाप्त हो रहा है: nextTick
वर्तमान ऑपरेशन समाप्त होते ही आग लग जाती है, अगला ईवेंट लूप शुरू होता है, सामान्य ईवेंट लूप चरण निष्पादित होते हैं, setImmediate
आग लगाते हैं और पुन: step
प्रक्रिया को फिर से शुरू करने के लिए हमारे फ़ंक्शन को कॉल करते हैं। वर्तमान ऑपरेशन समाप्त होता है, nextTick
आग, आदि।
उपरोक्त कोड का आउटपुट होगा:
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
अब अपने पुनरावर्ती कॉल को step
अपने nextTick
हैंडलर में स्थानांतरित करने के बजाय ले जाएं 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);
अब जब हमने पुनरावर्ती कॉल को हैंडलर चीजों step
में स्थानांतरित कर दिया है तो यह nextTick
एक अलग क्रम में व्यवहार करेगा। ईवेंट लूप की हमारी पहली पुनरावृति step
एक setImmedaite
हैंडलर के साथ-साथ एक nextTick
हैंडलर को पंजीकृत करने के लिए चलती है । वर्तमान ऑपरेशन के बाद हमारे nextTick
हैंडलर की आग समाप्त हो जाती है जो पुन: कॉल करता है step
और दूसरे setImmediate
हैंडलर के साथ-साथ दूसरे nextTick
हैंडलर को पंजीकृत करता है । चूंकि एक nextTick
हैंडलर करंट ऑपरेशन के बाद फायर करता है, इसलिए एक nextTick
हैंडलर के भीतर एक nextTick
हैंडलर का पंजीकरण करने से दूसरा हैंडलर मौजूदा हैंडलर ऑपरेशन के खत्म होने के तुरंत बाद चलेगा। nextTick
संचालकों फायरिंग रखेंगे, कभी जारी रखने से मौजूदा घटना पाश को रोकने। हम अपने सभी के माध्यम से प्राप्त करेंगेnextTick
हैंडलर से पहले हम एक भी setImmediate
हैंडलर आग देखते हैं ।
उपरोक्त कोड का आउटपुट समाप्त हो रहा है:
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
ध्यान दें कि हमने पुनरावर्ती कॉल को बाधित नहीं किया था और इसे 10 पुनरावृत्तियों के बाद निरस्त कर दिया था, फिर nextTick
कॉल पुनरावृत्ति होते रहेंगे और कभी भी इवेंट लूप को अगले चरण तक जारी नहीं रखने देंगे। यह कैसे nextTick
अवरुद्ध किया जा सकता है जब पुनरावर्ती उपयोग किया जाता है, जबकि setImmediate
अगले ईवेंट लूप में आग लग जाएगी और एक दूसरे के setImmediate
भीतर से किसी अन्य हैंडलर को सेट करने से वर्तमान ईवेंट लूप बाधित नहीं होगा, जिससे यह ईवेंट लूप के चरणों को सामान्य रूप से निष्पादित करना जारी रखेगा।
उम्मीद है की वो मदद करदे!
पुनश्च - मैं अन्य टिप्पणीकारों से सहमत हूं कि दो कार्यों के नामों को आसानी से अदला-बदली किया जा सकता है क्योंकि nextTick
यह लगता है कि यह वर्तमान ईवेंट लूप के बजाय अगले ईवेंट लूप में आग लगाने वाला है, और वर्तमान लूप का अंत अधिक "तत्काल" है "अगले लूप की शुरुआत से। ओह ठीक है, यही हमें एक एपीआई परिपक्व के रूप में मिलता है और लोग मौजूदा इंटरफेस पर निर्भर करते हैं।