本文深入解析 express 路由中多中间件函数的执行顺序、参数传递规则及 `next()` 的作用机制,帮助开发者正确设计可扩展、可复用的中间件流程。
在 Express 中,app.get() 等 HTTP 方法不仅支持单个回调函数,更核心的能力是支持多个中间件函数按序串联执行。其签名形式为:
app.get(path, callback1, callback2, ...,callbackN);
这并非语法糖,而是 Express 中间件(Middleware)模型的基础体现——每个函数都是一个独立的中间件,按声明顺序从左到右依次调用。
每个中间件函数接收标准参数:(req, res, next)。其中:
例如:
const a = (req, res, next) => {
console.log('Middleware A');
next(); // 必须显式调用,否则阻塞
};
const b = (req, res, next) => {
console.log('Middleware B');
res.send('Done!'); // 终止链,不再调用 next()
};
app.get('/user/:id/edit', a, b); // 输出:A → B → 响应⚠️ 注意:若中间件未定义 next 参数(如 (req, res) => {...}),Express 仍会传入 next,但该参数被忽略——这等价于函数签名中未声明该形参,JavaScript 引擎自动丢弃多余实参(符合 ECMAScript 规范)。因此,是否接收 next 完全取决于函数签名,而非运行时“自动注入”。
next 并非 JavaScript 编译器提供,而是 Express 在内部遍历中间件数组时,动态构造并传入的闭包函数。它封装了“跳转到下一个中间件”的逻辑,并能识别 next('route')、next(new Error()) 等特殊调用,实现路由跳过或错误传递。
// 错误处理中间件(需四参数签名)
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// 路由级跳过(仅在路由处理器中有效)
app.get('/admin', auth, (req, res, next) => {
if (!req.user.isAdmin) return next('route'); // 跳过当前路由,尝试下一个匹配路由
res.send('Admin panel');
});const validateId = (req, res, next) => {
const { id } = req.params;
if (!/^\d+$/.test(id)) return res.status(400).send('Invalid ID');
next();
};掌握中间件链的执行模型与 next() 的精确语义,是写出健壮、可维护 Express 应用的关键一步。