题目
简述Express中间件的工作原理及next()函数的作用
信息
- 类型:问答
- 难度:⭐
考点
中间件概念,中间件执行流程,next函数作用
快速回答
Express中间件是在请求-响应周期中执行的功能函数链。核心要点:
- 中间件按声明顺序依次执行
next()函数将控制权移交下一个中间件- 每个中间件可访问请求对象(req)、响应对象(res)和next函数
- 未调用
next()将终止请求链
1. 中间件核心原理
Express中间件本质是函数队列,处理HTTP请求时按注册顺序执行。工作流程:
- 收到HTTP请求
- Express按
app.use()或路由方法的注册顺序调用中间件 - 每个中间件接收三个参数:
(req, res, next) - 中间件执行完成后必须调用
next()或终止响应
2. next()函数的作用
next()是移交控制权的关键:
- 调用
next()→ 执行队列中下一个中间件 - 不调用
next()→ 请求挂起(客户端无响应) - 调用
next('route')→ 跳过当前路由的剩余中间件(仅限路由处理器) - 调用
next(err)→ 触发错误处理中间件
3. 代码示例
const express = require('express');
const app = express();
// 中间件1:日志记录
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next(); // 必须调用next移交控制权
});
// 中间件2:身份验证
app.use('/api', (req, res, next) => {
if (req.headers.token === 'secret') {
next(); // 验证通过,执行下一个中间件
} else {
res.status(401).send('Unauthorized'); // 终止请求链
}
});
// 路由处理器(也是中间件)
app.get('/api/data', (req, res) => {
res.json({ data: 'Protected content' });
});
// 错误处理中间件(特殊签名)
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Server Error');
});
app.listen(3000);4. 最佳实践
- 顺序敏感:通用中间件(如日志、CORS)放在路由前
- 错误处理:错误处理中间件需放在所有路由之后
- 路由隔离:使用
router.use()为特定路由分组 - 异步处理:在异步操作中调用
next()需使用try/catch
5. 常见错误
- 忘记调用next():导致请求挂起(客户端超时)
- 多次发送响应:在调用next()后又调用
res.send() - 顺序错误:将路由处理器放在日志中间件之前
- 未处理异步错误:
// 错误示例 app.use(async (req, res, next) => { await someAsyncOperation(); // 如果抛出异常,进程崩溃 next(); }); // 正确做法 app.use(async (req, res, next) => { try { await someAsyncOperation(); next(); } catch (err) { next(err); // 传递至错误处理中间件 } });
6. 扩展知识
- 中间件类型:应用级中间件(
app.use)、路由级中间件(router.use)、错误处理中间件(4个参数)、内置中间件(express.json()) - 洋葱模型:中间件先正向执行(请求阶段),再逆向执行(响应阶段)
app.use((req, res, next) => { console.log('进入中间件1'); next(); // 移交控制权 console.log('离开中间件1'); // 返回时执行 }); - 性能优化:在非必要中间件中尽早终止请求(如身份验证失败时)