Express.js中中间件与普通函数的适用场景及编码规范咨询
中间件 vs 普通函数:登录认证场景的选择指南
核心差异:设计理念与复用性
中间件本质是请求处理管道的拦截器,遵循「洋葱模型」,能在请求到达业务逻辑前后做链式处理;而普通函数更偏向单一功能的执行,没有天然的流程串联能力。
什么时候该用中间件?
- 全局/批量路由保护:如果大部分接口都需要登录认证,用中间件可以一次性挂载到路由组(比如
app.use('/api', authMiddleware)),不用在每个路由里手动调用普通函数,减少重复代码。 - 需要修改请求上下文:比如把解析后的用户信息挂载到
req.user,后续所有业务逻辑都能直接取用——普通函数虽然也能传参数,但没法直接修改req的全局上下文,手动传递会非常繁琐。 - 链式处理需求:如果认证后还要做权限校验、日志记录等前置操作,中间件可以直接链式串联(
authMiddleware -> permissionMiddleware -> logMiddleware),普通函数嵌套调用会让代码臃肿不堪。 - 适配框架生态:Express、Koa这类Node.js框架本身就设计了中间件机制,用中间件能贴合框架的请求处理流程,代码风格更统一。
什么时候该用普通函数?
- 单一路由的特殊认证逻辑:比如某个接口的认证规则和其他接口完全不同,单独写个普通函数调用更灵活,没必要为了一个路由拆中间件。
- 非请求链路的认证场景:比如后台脚本、定时任务里的身份校验,这些场景没有
req/res上下文,用普通函数更合适。 - 简单一次性逻辑:如果认证逻辑只是判断token是否存在,直接在路由里调用普通函数也没问题,没必要过度设计中间件。
为什么不一直用普通函数?
你说的「传递req/res给普通函数也能实现」没错,但中间件解决了普通函数的几个核心痛点:
- 自动传递上下文:框架会自动把
req/res/next传给中间件,不用你在每个路由里手动写auth(req, res),还要手动处理后续的放行逻辑。 - 错误处理统一:中间件里的错误可以通过
next(err)抛给全局错误处理中间件,普通函数的错误需要每个地方手动try/catch,代码冗余。 - 复用性更强:中间件可以抽成独立模块,在多个项目、多个路由组里复用;普通函数虽然也能复用,但集成到请求流程的成本更高。
举个直观对比:
普通函数实现
router.get('/profile', (req, res) => { const authResult = authFunction(req); if (!authResult.valid) { return res.status(401).send('Unauthorized'); } // 业务逻辑 res.send({ user: authResult.user }); });
每个路由都要重复写认证判断,繁琐且易漏。
中间件实现
// 定义中间件 const authMiddleware = (req, res, next) => { const token = req.headers.authorization?.split(' ')[1]; if (!token) { return res.status(401).send('Unauthorized'); } const user = verifyToken(token); req.user = user; next(); // 放行到业务逻辑 }; // 挂载到路由 router.get('/profile', authMiddleware, (req, res) => { // 直接用req.user,无需再处理认证 res.send({ user: req.user }); });
一次定义,多处复用,路由代码更干净。
总结
- 优先用中间件:当认证逻辑需要复用、修改请求上下文,或适配框架请求流程时。
- 用普通函数:当认证逻辑是单一特殊场景、非请求链路,或简单一次性逻辑时。
内容的提问来源于stack exchange,提问作者Anson Ng
相关产品推荐
相关产品推荐

