Node.js and Express: a server in JavaScript
Lesson 3 of 6
3Node.js and Express: a server in JavaScript
The big pictureWith Node you write the front and the back in one language. Express is the simplest and most widespread server framework, and its single idea (a middleware chain) exists in almost every server framework.
What the picture shows: Each middleware reads the request and decides: pass it on with next() or reply itself. Order in the code is order here.
Map of this part
The concepts in order, click any one to jump to it:
Two ways into the same idea
A server is like a restaurant: an order goes past reception (opens the envelope and reads it), then whoever logs the visit, then the chef for that dish, and if something burns a manager apologises politely. Each stop is a "middleware" in Express.
Node is a V8 runtime with a single-threaded event loop and non-blocking I/O (libuv), so waiting on the network or disk does not stall the server, but heavy computation does. Express builds an app as a chain of (req, res, next) functions, a Router groups routes, and the error handler is a four-argument function (err, req, res, next). In Express 5, errors from async handlers reach the error handler automatically.
Before You Start
🧰What a framework is
From the first two parts: a framework calls your functions, and Express is a small, flexible server framework.
⚡JavaScript
You know arrow functions and objects.
📨HTTP and REST
You know verbs and codes from the REST lesson.
The Core Idea
1The event loop: waiting without stopping
Node starts slow operations (a file, the network) and carries on with others, then returns when they are ready. This example shows the order: synchronous code first, then promises, then timers.
console.log("1 start");
setTimeout(() => console.log("4 timer"), 0);
Promise.resolve().then(() => console.log("3 promise"));
console.log("2 end of script");2Routes and the Router
app.get("/orders", handler) binds a verb and path to a function. req.params for segments (/orders/:id), req.query for what follows ?, and req.body for the body after express.json().
3Middleware: a chain in order
Middleware is a (req, res, next) function. It reads or changes the request and calls next(), or replies and ends the chain. Logging, authentication and JSON parsing are all middleware.
// a tiny middleware chain without Express, to see the idea run
function run(chain, req) {
let i = 0;
const next = (err) => {
const fn = chain[i++];
if (!fn) return;
if (err) return fn.length === 4 ? fn(err, req, next) : next(err);
if (fn.length === 4) return next();
try { fn(req, next); } catch (e) { next(e); }
};
next();
}
run([
(req, next) => { console.log("log:", req.method, req.path); next(); },
(req, next) => { if (!req.user) throw new Error("401 not logged in"); next(); },
(req, next) => console.log("handler: list orders"),
(err, req, next) => console.log("error handler ->", err.message),
], { method: "GET", path: "/orders", user: null });4Validation and the error handler
Trust no input: check type, length and allowed values and return 400 with a clear message. Make the last middleware an error handler that logs the error and replies 500 without exposing details to the user.
Worked example
A café orders API: list, create with validation, fetch by id with a 404, and a final error handler. Save it as server.js and run it with node server.js.
import express from "express";
const app = express();
app.use(express.json());
app.use((req, res, next) => {
const start = Date.now();
res.on("finish", () => console.log(req.method, req.path, res.statusCode, Date.now() - start + "ms"));
next();
});
const MENU = new Set(["latte", "mocha", "v60"]);
const orders = [];
app.get("/orders", (req, res) => res.json(orders));
app.post("/orders", (req, res) => {
const { item, cups } = req.body ?? {};
if (!MENU.has(item)) return res.status(400).json({ error: `item must be one of ${[...MENU]}` });
if (!Number.isInteger(cups) || cups < 1 || cups > 10) return res.status(400).json({ error: "cups must be 1-10" });
const order = { id: orders.length + 1, item, cups };
orders.push(order);
res.status(201).location(`/orders/${order.id}`).json(order);
});
app.get("/orders/:id", (req, res) => {
const order = orders.find((o) => o.id === Number(req.params.id));
if (!order) return res.status(404).json({ error: "no such order" });
res.json(order);
});
app.use((err, req, res, next) => { // four arguments: the error handler
console.error(err);
res.status(500).json({ error: "something went wrong" });
});
app.listen(3000, () => console.log("http://localhost:3000"));curl -s localhost:3000/orders -H 'content-type: application/json' -d '{"item":"latte","cups":2}'
curl -s localhost:3000/orders/1
curl -s -o /dev/null -w "%{http_code}\n" localhost:3000/orders/99Myth vs Reality
| Myth | Reality |
|---|---|
| Node cannot handle real servers because it is single-threaded. | It excels at heavy I/O (APIs, chat) and struggles only with heavy computation inside a request. |
| Express is old and nobody uses it. | It is still among npm's most downloaded packages, and version 5 is out. Fastify (used in Darb) is a faster alternative with the same idea. |
Test your understanding
What prints first: console.log, then setTimeout(0), then Promise.then?
Promises (microtasks) run before timers once synchronous code finishes.
How does Express know a middleware is an error handler?
A (err, req, res, next) function with four arguments is treated as an error handler.
A request arrives with cups: "lots". What do you reply?
The input is the client's mistake, so reply 4xx with a message saying what is expected.
Quick review cards
Check Your Understanding
Why does the error handler go last in the file?
Because middleware runs in order and an error skips forward to the first four-argument middleware.
When do you reply 201 with a Location header?
After creating a new resource; the header says where to find it.
What happens if you forget next() in middleware that does not reply?
The request hangs with no reply until the client times out.
Resources for this lesson
Grouped by type. Start with the official docs for precision, or an article or video for the explanation.
Done with this lesson?
Sign in to save your progress.