আগের Event Loop পাঠ সাধারণ model কভার করেছে — call stack, task queue। Node সেই model-এর উপর আরো দুটো নির্দিষ্ট scheduling tool যোগ করে, দুটোই মোটামুটি "এটা খুব শীঘ্রই চালান" বোঝায়, কিন্তু ঠিক একই না।
process.nextTick-এ পাঠানো একটা callback বর্তমান operation শেষ হওয়ার সাথে সাথেই চলে, event loop অন্য কিছুতে যাওয়ার আগে — এমনকি promise callback-এরও আগে।
console.log('1')
process.nextTick(() => console.log('2 — nextTick'))
Promise.resolve().then(() => console.log('3 — promise'))
console.log('4')
// Output: 1, 4, 2, 3 — nextTick promise microtask-এর আগে চলেEvent loop-এর একটা নির্দিষ্ট পরের phase-এ চলার জন্য schedule করা, সেই cycle-এর জন্য I/O callback (যেমন একটা সম্পূর্ণ হওয়া file read) চলার পরে।
const fs = require('fs')
fs.readFile(__filename, () => {
setTimeout(() => console.log('timeout'), 0)
setImmediate(() => console.log('immediate'))
})
// একটা I/O callback-এর ভেতরে, setImmediate ধারাবাহিকভাবে
// একটা 0ms setTimeout-এর আগে চলে — একটার বাইরে, ক্রম নিশ্চিত না| Tool | কখন চলে |
|---|---|
| process.nextTick() | বর্তমান operation-এর সাথে সাথেই — promise সহ বাকি সবকিছুর আগে |
| Promise .then() / microtask | nextTick callback-এর পরে, তবু event loop এগিয়ে যাওয়ার আগে |
| setImmediate() | event loop-এর "check" phase-এ, সাধারণত I/O callback-এর পরে |
| setTimeout(fn, 0) | timers phase-এ — setImmediate-এর মতো timing, কিন্তু প্রথম হওয়া নিশ্চিত না |
process.nextTick-এর একটা আসল বিপদ
একটা থামানোর শর্ত ছাড়া recursively process.nextTick call করা পুরো event loop-কে অভুক্ত রাখে — অন্য কিছুই (I/O না, timer না) কখনো পালা পায় না, কারণ nextTick callback অন্য কিছু চলার আগে সম্পূর্ণভাবে খালি করা হয়।
process.nextTick: বর্তমান synchronous কোড শেষ হওয়ার পরে, কিন্তু কঠোরভাবে যেকোনো I/O বা timer-এর আগে একটা callback চলা নিশ্চিত করা — সাবধানে ব্যবহার করা, আর সাধারণ application কোডে কমই দরকার।setImmediate: pending I/O handle হওয়ার পর পর্যন্ত কাজ পিছিয়ে দেওয়া, যাতে এটা বেশি time-sensitive কিছু দেরি না করায়।