मुझे लगता है कि मैं इसे काफी अच्छी तरह से समझा सकता हूं। चूंकि 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यह लगता है कि यह वर्तमान ईवेंट लूप के बजाय अगले ईवेंट लूप में आग लगाने वाला है, और वर्तमान लूप का अंत अधिक "तत्काल" है "अगले लूप की शुरुआत से। ओह ठीक है, यही हमें एक एपीआई परिपक्व के रूप में मिलता है और लोग मौजूदा इंटरफेस पर निर्भर करते हैं।