Summary
Macrotasks (setTimeout, I/O, render) run one per turn; microtasks (Promise.then, queueMicrotask) drain fully before the next macrotask. await schedules continuation as microtask — order matters for race bugs. Long microtask chains block paint and input (INP). Never assume setTimeout(0) runs before a resolved Promise.
Code example
console.log('sync');
Promise.resolve().then(() => console.log('microtask'));
setTimeout(() => console.log('macrotask'), 0);
// Output: sync → microtask → macrotask
Key points
- Macrotasks (setTimeout, I/O, render) run one per turn; microtasks (Promise.then, queueMicrotask) drain fully before the next macrotask.
awaitschedules continuation as microtask — order matters for race bugs.- Long microtask chains block paint and input (INP).
- Never assume
setTimeout(0)runs before a resolved Promise.