What You'll Learn
How JavaScript handles asynchronous operations using a single thread. Understand the V8 engine, Call Stack, Web APIs, Task Queue, Microtask Queue, and the Event Loop.
The Single-Threaded Nature of JS
JavaScript is a single-threaded, non-blocking, asynchronous, concurrent language. What does that mean? It means JS has exactly one Call Stack and can only do one thing at a time. If a function takes 5 seconds to run, the browser freezes for 5 seconds.
So how can Node.js handle millions of concurrent HTTP requests without freezing? The answer is the Event Loop.
The Browser / Node.js Environment
The JavaScript engine (like V8 in Chrome/Node) doesn't run in isolation. The environment provides extra tools:
1. The Call Stack
Where functions go to be executed. Last-In-First-Out (LIFO).
2. Web APIs / C++ APIs
Extra features provided by the browser/Node (e.g., setTimeout, DOM, fetch/HTTP requests, fs modules).
3. Callback Queue (Task Queue)
Where asynchronous callbacks (like a completed setTimeout) wait to be executed. First-In-First-Out (FIFO).
4. Microtask Queue
High priority queue specifically for Promises (e.g., .then()). Executes before the Callback Queue.
The Event Loop's Only Job
The Event Loop is a continuous loop that checks two things:
1. Is the Call Stack empty?
2. If yes, take the first thing in the Microtask Queue and push it to the stack.
3. If Microtasks are empty, take the first thing in the Callback Queue and push it to the stack.
}
The Classic Interview Question
What is the output of the following code?
console.log("1");
setTimeout(function() {
console.log("2");
}, 0);
Promise.resolve().then(function() {
console.log("3");
});
console.log("4");
Step-by-Step Execution:
console.log("1")goes on the stack. Prints 1. Pops off.setTimeoutgoes on the stack. It's a Web API, so the browser takes it and starts the 0ms timer. The callback function is immediately pushed to the Callback Queue.Promise.resolve()creates a resolved promise. Its.then()callback is pushed to the Microtask Queue.console.log("4")goes on the stack. Prints 4. Pops off.- The script finishes. The Call Stack is now empty.
- The Event Loop checks the Microtask Queue first. It finds the Promise callback, pushes it to the stack. Prints 3.
- The Event Loop checks the Microtask Queue again. It's empty. It checks the Callback Queue. Finds the setTimeout callback. Prints 2.
Output: 1, 4, 3, 2
Why node.js can be blocked
If you run a heavy computation (like an infinite while loop or a massive JSON parse) on the main thread, the Call Stack never empties. The Event Loop gets stuck, and your server won't be able to process any new incoming HTTP requests. Always offload heavy CPU tasks to Worker Threads!