How Node.js Works: The Event Loop and Non-Blocking I/O
The single execution model that explains why async, timers, and streams behave the way they do
- explain what runs on the single main thread and what does not;
- trace how the call stack, the event loop, and its queues cooperate;
- name the event loop's phases and what each one drains;
- predict the order of
setTimeout,setImmediate,Promise, andprocess.nextTick; - recognise blocking code and understand why it freezes an entire server.
One thread, one call stack
Node runs your JavaScript on a single thread with a single call stack. The call stack is a list of the functions that are currently running: when you call a function it is pushed on top, and when it returns it is popped off. Only the function on top is executing at any instant.
Because there is exactly one stack, two lines of your JavaScript can never truly run at the same moment. The engine (V8) takes one bite of work, runs it to completion, then takes the next. This is why you never see a variable half-updated by another thread: JavaScript code is run-to-completion. A function is not interrupted partway through by some other callback; that other callback has to wait until the stack is empty again.
This single-threaded model is the prerequisite for everything else in this lesson. If you remember one sentence, make it this: a callback can only start when the call stack is empty. The event loop's whole job is to decide which callback goes onto that empty stack next.
Analogy. Picture one chef in a kitchen (the thread). The chef can only do one action at a time. But a smart chef does not stand and stare at the oven while a cake bakes -- they set a timer, start chopping vegetables, and return to the cake when the timer rings. The oven, the timer, and the delivery driver are helpers outside the chef. The event loop is the chef's habit of always checking "what is ready for me now?" before starting the next task.