中间件本质上是一个可以访问请求、响应对象以及应用程序请求-响应周期中下一个中间件的函数,在JavaScript中通常通过函数组合的方式实现,核心作用是拦截和处理请求流程中的逻辑,避免业务代码过度耦合。

中间件的核心原理
JavaScript中的中间件大多基于洋葱模型实现,请求进入后会依次经过各个中间件的前置处理逻辑,到达最内层后返回,再依次经过各个中间件的后置处理逻辑。最基础的中间件函数结构如下:
// 基础中间件函数
function middleware(req, res, next) {
// 前置处理逻辑,比如记录请求日志
console.log(`收到请求:${req.method} ${req.url}`);
// 调用next执行下一个中间件
next();
// 后置处理逻辑,比如记录响应日志
console.log('请求处理完成');
}自定义简单中间件系统
我们可以自己实现一个简易的中间件注册和执行系统,理解中间件的调度逻辑:
class MiddlewareSystem {
constructor() {
// 存储所有注册的中间件
this.middlewares = [];
}
// 注册中间件
use(middleware) {
this.middlewares.push(middleware);
}
// 执行中间件
execute(req, res) {
let index = 0;
// 定义next函数,用于执行下一个中间件
const next = () => {
if (index >= this.middlewares.length) return;
const currentMiddleware = this.middlewares[index];
index++;
// 调用当前中间件,传入req、res和next函数
currentMiddleware(req, res, next);
};
// 启动第一个中间件
next();
}
}
// 使用示例
const system = new MiddlewareSystem();
// 注册第一个中间件:记录请求时间
system.use((req, res, next) => {
req.startTime = Date.now();
console.log('第一个中间件:开始处理请求');
next();
console.log(`第一个中间件:请求耗时${Date.now() - req.startTime}ms`);
});
// 注册第二个中间件:模拟请求处理
system.use((req, res, next) => {
console.log('第二个中间件:处理业务逻辑');
res.data = { code: 200, msg: '处理成功' };
next();
});
// 模拟请求和响应对象
const req = { method: 'GET', url: '/api/test' };
const res = {};
// 执行中间件系统
system.execute(req, res);
console.log('最终响应结果:', res.data);Express框架中的中间件使用
Express是Node.js中常用的Web框架,内置了完善的中间件机制,使用起来非常便捷:
const express = require('express');
const app = express();
// 全局中间件:解析JSON请求体
app.use(express.json());
// 自定义全局中间件:记录所有请求日志
app.use((req, res, next) => {
console.log(`[${new Date().toLocaleString()}] ${req.method} ${req.url}`);
next();
});
// 路由级中间件:仅对/api路径生效
app.use('/api', (req, res, next) => {
console.log('进入API路由中间件');
next();
});
// 错误处理中间件,参数包含err对象,必须放在所有中间件最后
app.use((err, req, res, next) => {
console.error('发生错误:', err.message);
res.status(500).json({ code: 500, msg: '服务器内部错误' });
});
// 定义接口
app.get('/api/user', (req, res) => {
res.json({ code: 200, data: { name: '张三', age: 18 } });
});
app.listen(3000, () => {
console.log('服务启动在3000端口');
});中间件使用注意事项
- 每个中间件中如果不调用
next()函数,请求流程会被中断,后续的路由和中间件都不会执行 - 中间件的注册顺序决定了执行顺序,建议把通用逻辑的中间件放在前面,业务特定的放在后面
- 错误处理中间件必须接收四个参数,且要放在所有普通中间件和路由的后面,才能捕获前面的错误
- 不要在中间件中执行耗时过长的同步操作,会阻塞整个请求流程,耗时操作建议用异步方式处理
常见应用场景
中间件在JavaScript开发中有很多实用场景,比如请求鉴权、参数校验、日志上报、异常捕获、响应数据格式化等。通过拆分这些逻辑到独立的中间件,可以让核心业务代码更简洁,也方便后续扩展和维护。
JavaScript中间件函数式编程Express洋葱模型修改时间:2026-06-06 07:46:51