Interview question
What is 'starvation' in the event loop and how can microtasks cause it? Event loop में 'starvation' क्या है और microtasks इसे कैसे cause कर सकते हैं?
Answer
Since the microtask queue must be FULLY drained before the event loop moves to the next macrotask, a microtask that keeps scheduling more microtasks can starve macrotasks (like rendering or timers) indefinitely.
// DANGEROUS - infinite microtask loop starves everything else
function infiniteMicrotasks() {
Promise.resolve().then(() => {
console.log('microtask running...');
infiniteMicrotasks(); // schedules ANOTHER microtask before this one finishes
});
}
// infiniteMicrotasks(); // this would freeze the page - setTimeout, rendering,
// and even user input would NEVER get a chance to run, since the event loop
// can't move past 'drain the microtask queue' step
// setTimeout scheduled alongside this would NEVER fire:
setTimeout(() => console.log('This never runs if microtasks starve the loop'), 0);
// SAFER pattern - use setTimeout/macrotask to yield control periodically
function safeRecursiveWork(remaining) {
if (remaining <= 0) return;
console.log(`Processing... ${remaining} left`);
setTimeout(() => safeRecursiveWork(remaining - 1), 0);
// setTimeout yields to the macrotask queue, allowing rendering and
// other events to run BETWEEN each step, unlike a microtask loop
}
safeRecursiveWork(1000000); // page stays responsive throughout
// Practical guideline: use Promise chains/microtasks for logically
// connected async steps, but for long-running iterative work, periodically
// yield with setTimeout(fn, 0) or requestIdleCallback to keep the UI responsiveचूंकि microtask queue को अगले macrotask पर जाने से पहले पूरी तरह drain होना ज़रूरी है, एक microtask जो लगातार और microtasks schedule करता रहे वो macrotasks (जैसे rendering या timers) को indefinitely starve कर सकता है।
// खतरनाक - infinite microtask loop सब कुछ starve करता है
function infiniteMicrotasks() {
Promise.resolve().then(() => {
console.log('microtask चल रहा है...');
infiniteMicrotasks(); // इसके पूरा होने से पहले एक और microtask schedule करता है
});
}
// infiniteMicrotasks(); // page freeze हो जाएगा - setTimeout, rendering,
// यहां तक कि user input भी कभी chance नहीं पाएगा
// इसके साथ scheduled setTimeout कभी नहीं चलेगा:
setTimeout(() => console.log('यह कभी नहीं चलेगा अगर microtasks loop starve कर दें'), 0);
// सुरक्षित pattern - setTimeout/macrotask से periodically control yield करना
function safeRecursiveWork(remaining) {
if (remaining <= 0) return;
console.log(`Processing... ${remaining} बाकी`);
setTimeout(() => safeRecursiveWork(remaining - 1), 0);
// setTimeout macrotask queue को yield करता है, rendering और अन्य
// events को हर step के बीच चलने देता है
}
safeRecursiveWork(1000000); // page पूरे समय responsive रहता हैWas this answer clear?