SyntaxStudy
Sign Up
Express.js The Middleware Chain and next()
Express.js Beginner 1 min read

The Middleware Chain and next()

The `next()` function is the mechanism that advances control through the middleware stack. Calling `next()` with no arguments moves to the next matching middleware or route. Calling `next('route')` skips remaining handlers on the current route and moves to the next matching route. Calling `next(err)` — passing any truthy value — skips all remaining non-error middleware and jumps straight to error-handling middleware. This design means you can compose complex request processing pipelines from small, focused functions. A request might pass through a rate-limiter, then an authentication checker, then a permission validator, each implemented as a separate middleware function that calls `next()` on success. Avoiding common mistakes is critical: if you forget to call `next()` and also forget to send a response, the request will hang until the client times out. Always ensure every code path in a middleware either calls `next()`, calls `next(err)`, or sends a response.
Example
const express = require('express');
const app     = express();
app.use(express.json());

// Middleware 1 – rate limiter (simplified)
const hits = {};
function rateLimit(req, res, next) {
    const ip = req.ip;
    hits[ip] = (hits[ip] || 0) + 1;
    if (hits[ip] > 100) {
        return res.status(429).json({ error: 'Too Many Requests' });
    }
    next(); // pass to middleware 2
}

// Middleware 2 – auth check
function authenticate(req, res, next) {
    const token = req.headers.authorization?.split(' ')[1];
    if (!token) return next(new Error('No token provided')); // → error handler
    req.userId = 'user-123'; // decoded from token in real code
    next(); // pass to route handler
}

// Route with two middleware in sequence
app.get('/profile', rateLimit, authenticate, (req, res) => {
    res.json({ userId: req.userId });
});

// Error-handling middleware (4 args, registered last)
app.use((err, req, res, next) => {
    console.error(err.message);
    res.status(err.status || 500).json({ error: err.message });
});

app.listen(3000);