πŸ”΄ HardEvent Loop TrapsπŸ› Debug Challenge

Microtask starvation β€” UI never updates

Buggy Code β€” Can you spot the issue?

function infiniteLoop() {
  return Promise.resolve().then(() => infiniteLoop());
}

infiniteLoop();
// The UI is now completely frozen

Fixed Code

// 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 Explained

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.

More Event Loop Traps Debug Challenges

🟑 MediumUI update blocked by sync codeβ†’πŸŸ‘ MediumsetTimeout inside a loop β€” all fire at onceβ†’πŸ”΄ HardGenerator function called synchronously inside Promiseβ†’πŸŸ‘ MediumMixing microtasks and DOM updatesβ†’

Practice spotting bugs live β†’

38 debug challenges with AI hints

πŸ› Try Debug Lab