mediumFrontend EngineerStreaming
Explain the JavaScript Event Loop — how do microtasks and macrotasks differ, and how does this affect async/await execution order?
Posted 18/04/2026
by Mehedy Hasan Ador
Question Details
At a video streaming company, the interviewer showed this code and asked for the output order:
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => {
console.log('3');
}).then(() => {
console.log('4');
});
async function foo() {
console.log('5');
await Promise.resolve();
console.log('6');
}
foo();
console.log('7');
What is the output and why?Suggested Solution
Output: 1, 5, 7, 3, 6, 4, 2
Execution Breakdown
Phase 1: Synchronous (Call Stack)
1 → logged immediately
5 → foo() is called, logs 5 synchronously
7 → logged immediately
Phase 2: Microtask Queue (resolved Promises, await continuation)
3 → Promise.resolve().then() callback
6 → await resolves, continuation of foo()
4 → second .then() chains after 3
Phase 3: Macrotask Queue (setTimeout, setInterval, I/O)
2 → setTimeout callback (even with 0 delay)
Key Rules
Promise.then(), await, queueMicrotask()setTimeout, setInterval, I/OCritical Detail: async/await
async function foo() {
console.log('5'); // Synchronous — runs immediately
await Promise.resolve(); // Yields — rest becomes microtask
console.log('6'); // Microtask — runs in microtask phase
}
await effectively does: Promise.resolve(value).then(restOfFunction)Why This Matters in Production
1. UI Blocking: A long chain of microtasks can block rendering because microtasks ALL complete before the next frame2. Timer Unreliability:
setTimeout(fn, 0) doesn't run at 0ms — minimum is 4ms in browsers, and it waits for all microtasks3. State Consistency: React's concurrent mode relies on microtask scheduling for batched updates
// BAD: Blocks rendering with microtask chain
function processItems(items) {
items.forEach(item => {
Promise.resolve().then(() => heavyProcess(item));
});
}
// BETTER: Yields to browser between items
async function processItems(items) {
for (const item of items) {
heavyProcess(item);
await new Promise(r => setTimeout(r, 0)); // yields to macrotask
}
}