前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Express 中间件执行顺序
全栈全栈开发Express 服务

Express 中间件按什么顺序执行,顺序写错会发生什么?

Express 中间件按注册顺序执行,路径前缀匹配决定候选,两者共同决定执行链;错误处理中间件必须放在所有其他中间件之后,否则永远收不到错误。

前端进阶之旅 · 一题精讲更新于 2026.09.05
全栈开发#Express 服务#路由
先看核心答案
理解线索

执行链的两个决定因素

  1. 注册顺序app.use 与路由按书写先后进入同一条队列
  2. 前缀匹配挂载路径是请求路径前缀才进入候选
  3. next 传递只有调 next() 控制权才沿链向下走

app.use('/api') 对 /api/users 也匹配,因为它是前缀而非精确匹配。

核心回答

先记住这个答案

Express 把每个请求交给一条按代码注册顺序排列的中间件队列,逐个检查挂载路径是否匹配当前请求路径的前缀,匹配且调用 next() 才轮到下一个。路由处理函数本质上也是这条链上的中间件。顺序写错的典型后果是:把错误处理中间件(四参数函数)放在路由之前,它只会在链上被跳过,路由里抛错后它收不到 next(err),最终错误落到内置默认处理器或进程崩溃。判断口诀:解析类中间件在前,路由居中,404 与错误处理垫底。

  • 执行顺序由注册顺序加路径前缀匹配决定
  • 错误处理中间件必须注册在所有其他中间件之后
  • 不发响应必须调 next(),否则请求挂起

注册顺序与路径前缀如何共同决定执行链

Express 内部维护一条扁平的中间件层数组,每次调用 app.use、app.get 等都按调用先后往数组里压入一层。请求到来时从头遍历:先检查该层的挂载路径是否为请求路径的前缀(不带路径的 app.use 等价于挂载在 /,匹配一切),匹配则执行该层函数,函数里调用 next() 才继续向后找下一层匹配项。

因此最终执行链是两个条件的交集:写在前面且路径匹配。一个挂在 /admin 的鉴权中间件无论写多靠前,对 /api/list 都不会执行;同样,即使路径匹配,写在路由之后的普通中间件也轮不到,因为路由通常直接 res.send 结束了响应周期。路由处理函数在机制上就是链上的一层,只是按 HTTP 方法再过滤一次。

把错误处理中间件写在路由之前导致线上 500 兜底失效

假设一个项目约定所有业务错误统一返回 JSON:{ code, message },开发者把四参数的错误处理中间件写在文件顶部、app.get('/orders') 等路由之前。在预期场景中,当订单接口查询数据库超时抛错时,客户端不会收到约定的 JSON,而是 Express 默认处理器返回的 HTML 堆栈页,监控也无法按 code 字段聚合告警。

原因是错误处理中间件必须位于错误产生点之后:路由里 throw 或 next(err) 时,Express 从当前位置向后查找第一个四参数层,写在路由之前的层已经在普通流程里被跳过(普通流程中四参数层不参与匹配),永远不会被错误链重新找到。修复方法是把它移到所有路由和 404 中间件之后,顺序变为解析器、业务路由、404、错误处理。

顺序规则在哪些条件下容易误判

容易误判的第一处是 next('route') 与 next() 的区别:在 app.get 的多个回调里,next() 只是进入同一路由的下一个回调,并非进入下一个中间件层;第二处是 Router,router.use 的相对路径叠加上 app.use('/api', router) 的前缀,执行顺序按挂载点展开,阅读单个文件容易看错全局顺序。

对应处理:排查顺序问题时,以应用入口文件为准,把所有 app.use 与路由注册按行号列出来,再逐条核对前缀;用日志中间件临时打印 req.method 与 req.originalUrl 验证实际链路。代价是模块化项目中链路被拆散到多个 Router 文件,需要约定每个 Router 内部自包含其私有中间件,避免跨文件的隐式顺序依赖。

回答前,多想一步

容易答错的地方

错误处理中间件放前面也能兜底
错误。普通请求流程中四参数层被跳过,错误发生时 Express 只从出错位置向后找四参数层,写在路由之前的错误处理器不会被调用,错误会落到内置默认处理器。
app.use 不带路径就只执行一次
不带路径的 app.use 挂载在 /,对每个进入应用的请求都按顺序执行一次,不是启动时执行一次。若其中既不发响应也不调 next(),后续所有请求都会挂起。
试着用自己的话回答

面试官还会怎么问?

路径匹配是精确匹配还是前缀匹配?

app.use 是前缀匹配,app.use('/api') 会匹配 /api、/api/users;app.get 等路由方法是整路径匹配。判断某层是否进入执行链时先看这个区别。

路由之后还能有中间件被执行吗?

可以,但前提是路由处理函数不调响应方法而调 next(),此时控制权继续向后走,常用于统一记录响应日志或后置处理;一旦发送了响应,再调 next() 容易引发重复发送错误。

多个 app.use 挂同一路径,顺序怎么定?

严格按代码书写顺序逐个执行,前一个调 next() 才轮到后一个,形成挂载点上的子栈。把鉴权写在校验之后,就会出现未鉴权请求先触发校验逻辑的问题。

从一道题,走向一组知识

把知识连起来

Express 服务

Express 中 app.use() 和 router.use() 挂载中间件有什么实际差异?

同属「Express 服务」专题,接着看 Express app.use 与 router.use 区别 在具体场景中的处理方式。

Express 服务

Express 中间件既不发响应也不调用 next() 会导致什么后果,如何排查?

同属「Express 服务」专题,接着看 Express 中间件忘记调用 next 请求挂起 在具体场景中的处理方式。

Express 服务

Express 一个路由挂多个处理函数(数组或多次 app.get)时执行规则是什么?

同属「Express 服务」专题,接着看 Express 路由 多个回调函数 在具体场景中的处理方式。

参考资料

  • Using middleware

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 注册顺序与路径前缀如何共同决定执行链
  3. 把错误处理中间件写在路由之前导致线上 500 兜底失效
  4. 顺序规则在哪些条件下容易误判
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑