You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express.js中中间件与普通函数的适用场景及编码规范咨询

中间件 vs 普通函数:登录认证场景的选择指南

核心差异:设计理念与复用性

中间件本质是请求处理管道的拦截器,遵循「洋葱模型」,能在请求到达业务逻辑前后做链式处理;而普通函数更偏向单一功能的执行,没有天然的流程串联能力。

什么时候该用中间件?

  • 全局/批量路由保护:如果大部分接口都需要登录认证,用中间件可以一次性挂载到路由组(比如app.use('/api', authMiddleware)),不用在每个路由里手动调用普通函数,减少重复代码。
  • 需要修改请求上下文:比如把解析后的用户信息挂载到req.user,后续所有业务逻辑都能直接取用——普通函数虽然也能传参数,但没法直接修改req的全局上下文,手动传递会非常繁琐。
  • 链式处理需求:如果认证后还要做权限校验、日志记录等前置操作,中间件可以直接链式串联(authMiddleware -> permissionMiddleware -> logMiddleware),普通函数嵌套调用会让代码臃肿不堪。
  • 适配框架生态:Express、Koa这类Node.js框架本身就设计了中间件机制,用中间件能贴合框架的请求处理流程,代码风格更统一。

什么时候该用普通函数?

  • 单一路由的特殊认证逻辑:比如某个接口的认证规则和其他接口完全不同,单独写个普通函数调用更灵活,没必要为了一个路由拆中间件。
  • 非请求链路的认证场景:比如后台脚本、定时任务里的身份校验,这些场景没有req/res上下文,用普通函数更合适。
  • 简单一次性逻辑:如果认证逻辑只是判断token是否存在,直接在路由里调用普通函数也没问题,没必要过度设计中间件。

为什么不一直用普通函数?

你说的「传递req/res给普通函数也能实现」没错,但中间件解决了普通函数的几个核心痛点:

  1. 自动传递上下文:框架会自动把req/res/next传给中间件,不用你在每个路由里手动写auth(req, res),还要手动处理后续的放行逻辑。
  2. 错误处理统一:中间件里的错误可以通过next(err)抛给全局错误处理中间件,普通函数的错误需要每个地方手动try/catch,代码冗余。
  3. 复用性更强:中间件可以抽成独立模块,在多个项目、多个路由组里复用;普通函数虽然也能复用,但集成到请求流程的成本更高。

举个直观对比:

普通函数实现

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 04:15:42