What does this log and why? console.log(1); setTimeout(cb2); Promise.resolve().then(cb3); console.log(4);
Whether you know the microtask queue drains before the next macrotask.
Logs 1, 4, 3, 2. Synchronous code runs first (1, 4). Then the event loop drains ALL microtasks (Promise callbacks) before any macrotask (setTimeout) — so 3 before 2. The rule: after each task, the engine empties the entire microtask queue before rendering or picking up the next timer. The full model: the call stack runs synchronous code to completion; then, on each tick, the loop runs one macrotask (a timer callback, an I/O callback, a UI event), then drains the microtask queue COMPLETELY — including any microtasks those microtasks schedule — before the browser gets a chance to render and before the next macrotask. Microtasks: Promise .then/.catch/.finally, await continuations, queueMicrotask, MutationObserver. Macrotasks: setTimeout/setInterval, message events, I/O. This is why an infinite chain of promises can starve rendering (microtasks never yield), while setTimeout loops let frames paint between iterations.
Explaining why a Promise .then beats a setTimeout(0), why await resumes 'soon' but not synchronously, and starvation bugs where microtasks block rendering.