I think no one can explain this better than the Node.js official docs.
Some key parts:
What is the Event Loop?
The event loop is what allows Node.js to perform non-blocking I/O
operations — despite the fact that JavaScript is single-threaded — by
offloading operations to the system kernel whenever possible.
Since most modern kernels are multi-threaded, they can handle multiple
operations executing in the background. When one of these operations
completes, the kernel tells Node.js so that the appropriate callback
may be added to the poll queue to eventually be executed. We'll
explain this in further detail later in this topic.
Event Loop Explained
When Node.js starts, it initializes the event loop, processes the
provided input script (or drops into the REPL, which is not covered in
this document) which may make async API calls, schedule timers, or
call process.nextTick(), then begins processing the event loop.
The following diagram shows a simplified overview of the event loop's
order of operations.
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ pending callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
note: each box will be referred to as a
"phase" of the event loop.
Each phase has a FIFO queue of callbacks to execute. While each phase
is special in its own way, generally, when the event loop enters a
given phase, it will perform any operations specific to that phase,
then execute callbacks in that phase's queue until the queue has been
exhausted or the maximum number of callbacks has executed. When the
queue has been exhausted or the callback limit is reached, the event
loop will move to the next phase, and so on.
Since any of these operations may schedule more operations and new
events processed in the poll phase are queued by the kernel, poll
events can be queued while polling events are being processed. As a
result, long running callbacks can allow the poll phase to run much
longer than a timer's threshold. See the timers and poll sections for
more details.
NOTE: There is a slight discrepancy between the Windows and the
Unix/Linux implementation, but that's not important for this
demonstration. The most important parts are here. There are actually
seven or eight steps, but the ones we care about — ones that Node.js
actually uses - are those above.
Phases Overview
timers: this phase executes callbacks scheduled by setTimeout() and
setInterval(). pending callbacks: executes I/O callbacks deferred to the next loop iteration. idle, prepare: only used internally. poll: retrieve new I/O events; execute I/O related callbacks (almost all with the exception of close callbacks, the ones scheduled by timers, and setImmediate()); node will block here when appropriate. check:
setImmediate() callbacks are invoked here. close callbacks: e.g.
socket.on('close', ...). Between each run of the event loop, Node.js
checks if it is waiting for any asynchronous I/O or timers and shuts
down cleanly if there are not any.