The Event-Driven, Non-Blocking Model
Node.js works differently from many programs you may know. Instead of doing one thing at a time and waiting for each step to finish, it starts a task, moves on, and comes back when the task is done. This is called non-blocking I/O. "I/O" means input and output — reading files, talking to the network, and so on. "Non-blocking" means Node does not sit still while waiting.
Think of a restaurant cook. A blocking cook takes one order, cooks it, serves it, then takes the next order. A non-blocking cook takes all the orders at once, puts food on the stove, and plates each dish as it becomes ready.
How the Event Loop Works
The event loop is the part of Node.js that keeps this moving. It is a simple repeating cycle:
- Node starts a task, like reading a file.
- While the task runs, Node handles other work.
- When the task finishes, it joins a queue — a waiting line.
- The event loop picks finished tasks from the queue and runs their follow-up code.
You do not write the event loop. You just hand Node functions to run when things finish. Those functions are called callbacks — functions that "call back" when the work is done.
const { readFile } = require('node:fs/promises');
console.log('Start');
async function main() {
const text = await readFile('notes.txt', 'utf8');
console.log('File read!');
}
main();
console.log('End');"End" prints before "File read!" because reading the file happens in the background while the rest of the code runs.
Organizing Code with Modules
A module is a file that shares its code with other files. Node programs are split into modules to stay tidy.
// greet.js
function greet(name) {
return `Hello, ${name}!`;
}
module.exports = greet;// app.js
const greet = require('./greet');
console.log(greet('Node'));module.exports says what the file gives out. require pulls that in.
Managing Dependencies with npm
You do not have to build everything yourself. npm is Node's package manager — a tool that downloads ready-made code, called packages, that others have shared.
Run npm init to create a package.json file. This file lists your project's packages, like a shopping list. Then npm install <name> adds a package and records it in the list. Anyone with your package.json can reinstall everything with one command: npm install.
Exercise
Why does "End" print before "File read!" in the example above?
Show answer
Reading the file is non-blocking. Node starts the read, continues running the rest of the script, and the event loop runs the follow-up code only when the file is ready.
Spotted a mistake, or code that does not work?