Prompt
Given this snippet, write predictOrder() returning the labels in the exact order they log:
log('A')
setTimeout(() => log('B'), 0)
Promise.resolve().then(() => log('C'))
Promise.resolve().then(() => {
log('D')
setTimeout(() => log('E'), 0)
})
log('F')
Return an array of strings. No guessing — reason through sync → microtasks → macrotasks.
Solution
This ordering question is the fastest senior/junior separator in JavaScript interviews because it tests the model, not memorization: the call stack runs to completion, then the engine drains the entire microtask queue, and only then takes one macrotask — and repeats.
Walk it like a mentor would:
- Sync first, always.
AandFprint before any callback — nothing asynchronous can interleave with running synchronous code. JavaScript's single thread is a guarantee, not a limitation, here. - Microtasks drain completely. Both
.thencallbacks (C,D) run before anysetTimeout, even though the timeouts were scheduled earlier. Priority beats scheduling order. - Macrotasks go one per tick.
Bwas enqueued during sync execution;Ewas enqueued while draining microtasks — soBprecedesE.
The React Native tie-in that earns points: the bridge and InteractionManager live on this same loop — a long microtask chain (e.g. a .then that synchronously processes a huge JSON payload) starves timers and touch responsiveness exactly like a long sync block does.
Red flag: saying "setTimeout 0 runs immediately after the current line." It runs after sync code and after every pending microtask — and never sooner than the next tick.
Say it: "Sync runs to completion, the microtask queue drains fully, then one macrotask per tick — so promise callbacks always beat timers, and a microtask can starve the loop."