Predict this output before reading on
Most developers know JavaScript is single-threaded, yet this tiny program demonstrates that completion order is not source order. The event loop coordinates queued work after the current stack finishes.
console.log("one");
setTimeout(() => console.log("timeout"), 0);
Promise.resolve().then(() => console.log("promise"));
console.log("two");
// one, two, promise, timeoutThe queues that matter
Synchronous code runs until the call stack is empty. Promise reactions enter the microtask queue, which the browser drains before taking the next task such as a timer callback or input event. The browser gets opportunities to paint between tasks, not between every line of JavaScript.
Long synchronous code therefore blocks clicks, animations, and visual updates even if a spinner state was set at its beginning.
Connect this to real React behavior
React schedules rendering work, but it cannot make a blocking while loop responsive. If an event handler performs expensive parsing immediately after setLoading(true), the browser may not paint the loading UI until the parsing ends. Split work, move it to a worker, or change the interaction design.
Effects are not a timer queue. They synchronize React with an external system after a commit. A promise created in an effect still resumes later as a microtask when its awaited operation settles.
async function handleImport(file: File) {
setLoading(true);
// Consider a Web Worker for expensive parsing here.
const data = await file.text();
await save(data);
setLoading(false);
}Timing rules that hold up in production
Do not use setTimeout(0) as a guarantee that the screen has painted. Do not rely on promise ordering across independent requests. And do not try to fix heavy CPU work by wrapping it in a promise; it still runs on the same main thread when executed.
Use browser performance traces when an interaction feels slow. They reveal long tasks, network wait, rendering, and scripting time far more clearly than console logs.
Key Takeaways
- Microtasks such as promise callbacks run before the next timer task.
- JavaScript can be single-threaded while the browser coordinates asynchronous operations around it.
- Rendering responsiveness requires yielding or moving CPU-heavy work off the main thread.
Ready to explain this under interview pressure?
Learn the mental models, then practise applying them to realistic frontend problems.
Join Cohort 3 Waitlist