JavaScript is Single-Threaded
JavaScript executes on a single thread — it can only do one thing at a time. Yet it handles timers, network requests, and user events simultaneously. The secret is the Event Loop architecture.
// Sync runs first, async callbacks run later:
console.log("1");
setTimeout(() => console.log("2"), 0);
console.log("3");
// Output: 1, 3, 2
// The call stack, web APIs, callback queue, and event loop:
// 1. console.log("1") → stack → executes → pops
// 2. setTimeout → registers in Web APIs (timer), continues
// 3. console.log("3") → stack → executes → pops
// 4. Stack is empty → Event Loop checks callback queue
// 5. Timer callback → stack → console.log("2")
// Microtasks (Promises) have higher priority:
setTimeout(() => console.log("setTimeout"), 0);
Promise.resolve().then(() => console.log("Promise"));
console.log("Sync");
// Output: "Sync", "Promise", "setTimeout"
Blocking the Event Loop
// Long synchronous code blocks everything:
// Don't do this in browser:
function heavyComputation() {
let result = 0;
for (let i = 0; i < 2_000_000_000; i++) result += i;
return result;
}
// While this runs, UI freezes completely!
// Fix: break work into chunks:
function processChunked(items, processFn, done) {
let i = 0;
function step() {
const end = Math.min(i + 1000, items.length);
for (; i < end; i++) processFn(items[i]);
if (i < items.length) setTimeout(step, 0); // yield
else done();
}
step();
}
// Or use requestIdleCallback:
requestIdleCallback((deadline) => {
while (deadline.timeRemaining() > 0 && items.length > 0) {
processItem(items.shift());
}
});
⚡ Key Takeaways
- Single thread: one task at a time on the call stack
- Async operations (setTimeout, fetch) are handled by Web APIs — not blocking
- Microtasks (Promise callbacks) always run before macrotasks (setTimeout)
- Long sync code freezes the browser — chunk heavy work
- Even setTimeout(fn, 0) runs after all current sync code finishes
🎯 Practice Exercises
EXERCISE 1
Predict the exact output order of: 2 console.logs, 1 setTimeout(0), 2 Promise.resolve().then() calls. Then verify by running it.