← DojoJavaScript · TypeScriptThe event loop — why a promise beats setTimeout(0)

JavaScript is single-threaded: async callbacks wait in queues. Microtasks (promises) are fully drained before any macrotask (setTimeout). So a promise scheduled LATER still runs before a 0ms timer scheduled earlier. Run it and read the order.

Explicit over implicit
🔑 실무 용어 (say these in English)
  • event loopone thread runs code, then drains queued callbacksJS is single-threaded — the event loop runs my code, then drains queued callbacks.
  • microtask vs macrotaskpromises run before timersPromise callbacks are microtasks and drain before any setTimeout macrotask.
  • call stacksync frames run to completion firstSynchronous frames run to completion on the call stack before the loop continues.
  • non-blocking I/Oasync work yields so the thread stays freeAsync I/O yields the thread so the UI stays responsive.
⚖️ Trade-offs · 원리 (say these out loud)
  • A resolved promise's callback runs on the microtask queue, which the event loop fully drains after the current synchronous frame but BEFORE rendering, I/O, or any macrotask, whereas setTimeout(0) is a macrotask clamped to a ~4ms minimum and queued behind already-pending timers and rendering — so a promise wins precisely because microtasks have strictly higher priority than the timer phase.
  • The cost of that priority is starvation: because the loop empties the entire microtask queue before yielding, a chain of promises that keep enqueuing more microtasks can block rendering and starve I/O indefinitely, which is exactly the failure mode setTimeout(0) avoids by surrendering control back to the loop after one task.
  • Reach for queueMicrotask/Promise.resolve().then() when you need to defer work but still land before the next paint — e.g. batching state mutations or guaranteeing a callback runs after the current call stack unwinds without ever yielding to the browser.
  • Use setTimeout(0) (or better, requestAnimationFrame for visual work, or MessageChannel to dodge the 4ms clamp) precisely when you WANT to yield — to let the browser paint, process input, or break up a long task so the main thread stays responsive; choosing a microtask there is the bug, not the optimization.
코드 로딩…