function infiniteLoop() {
return Promise.resolve().then(() => infiniteLoop());
}
infiniteLoop();
// The UI is now completely frozen// Fix: Use setTimeout to yield to macrotask queue
function loop() {
setTimeout(() => {
doSomeWork();
loop(); // re-schedule as macrotask, not microtask
}, 0);
}
loop();
// Browser can now repaint between iterations
// Even better: requestAnimationFrame for visual updates
function animationLoop() {
doVisualUpdate();
requestAnimationFrame(animationLoop);
}
requestAnimationFrame(animationLoop);Bug: Microtasks drain completely before any macrotask (including repaints). A self-perpetuating Promise chain fills the microtask queue infinitely β the browser never gets to paint.
Explanation: Recursive Promises create an infinite microtask chain. Since microtasks drain before repaints, the browser is stuck. setTimeout re-schedules as a macrotask, letting the browser breathe.
Key Insight: Infinite microtask chains starve the browser. Use setTimeout/rAF for loops that should yield to the renderer.