Glossary / Microtask queue

Microtask queue

The microtask queue runs short jobs after the current JavaScript stack empties and before the host proceeds to a later task or rendering opportunity. Promise reactions, queueMicrotask, and MutationObserver callbacks use microtask scheduling in browsers. Microtasks provide ordering within an event-loop turn, but are not a way to yield to rendering or user input.

Ordering and starvation

console.log("start");
Promise.resolve().then(() => console.log("promise"));
queueMicrotask(() => console.log("queued"));
setTimeout(() => console.log("timer"), 0);
console.log("end");
// start, end, promise, queued, timer

Microtasks are processed until the queue is empty. A microtask can enqueue another microtask, which also runs before the next task. Recursive microtask production can therefore starve timers, input, and rendering. Promise callbacks always run asynchronously relative to the current synchronous stack, even when the Promise is already settled.

Use queueMicrotask for small consistency/cleanup work that must run after current synchronous code but before the next task; use a task or scheduler when the goal is to let the browser breathe. Exceptions thrown in a Promise reaction become rejections; an exception from queueMicrotask is reported as an uncaught exception (host reporting differs). Avoid turning large work into a microtask chain.

Interview questions

  1. When do microtasks run? At a microtask checkpoint after the current stack/job, before later task processing.
  2. Can microtasks enqueue more microtasks? Yes, and they are drained in the same checkpoint.
  3. Can this starve rendering? Yes.
  4. Promise callback or setTimeout(0), which first? Promise reaction microtasks generally run before the timer task.

References