前端进阶之旅前端进阶之旅
  • 基础篇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 一个路由挂多个处理函数(数组或多次 app.get)时执行规则是什么?

Express路由定义时传入的多个处理函数会按书写顺序组成一条链,后一个函数只有在前一个函数主动调用next()后才执行;一旦某个函数发送响应,链路即终止。

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

回调链的推进条件

  1. 顺序性先注册者先执行,后注册者等待移交
  2. next触发调用next()即跳至下一回调
  3. 响应即终止res.end()等结束链路,不再转发

若某回调既不next也不发响应,请求将一直挂起。

核心回答

先记住这个答案

多个处理函数既可以作为app.get('/path', fn1, fn2)的独立参数,也可以写成数组app.get('/path', [fn1, fn2]),还能混合使用。Express把同一路由上的所有函数按从左到右的顺序依次执行。每个函数必须接收next参数,并在需要继续时调用next();若函数调用res.send()等响应方法,则后续函数不再执行,请求处理结束。

  • 多个回调按声明顺序串联
  • next()是进入下一回调的唯一入口
  • 发响应后后续回调不会被调用

路由级回调链的流动规则

Express在处理app.get(path, fn1, fn2)时,会把所有传入的处理器函数收集到一个数组里,并把它们当作一条顺序链。当请求匹配该路径时,Express先调用链上的第一个函数,传入(req,res,next)。这个next是Express生成的内部函数,它的作用是把控制权交给当前链条中的下一个函数。如果第一个函数不调用next(),也没有结束响应,那么请求就停在它这里,后面的函数永远不会被触发。

如果某个函数调用了res.send()、res.json()、res.end()等,Express会认为响应已经发出,即使它之后又写了next(),调用也无效,因为响应流已经结束。更常见的是把回调按业务阶段拆分:校验、取数、响应。数组不是唯一写法,也可以连续写多个参数,如app.get('/p', a, b, c)。凡是出现在路由路径后的函数型参数都会并入处理器链,顺序由书写位置决定。

一个三段式用户查询场景

假设有GET /users/:id,需要先检查id是否由数字组成,然后从内存数组取用户,最后输出JSON。若id非法,期望直接返回400,不再继续查询和响应。于是定义checkId、fetchUser、sendUser三个函数,并组合成app.get('/users/:id', checkId, fetchUser, sendUser)。checkId中解析req.params.id,发现不是正整数就res.status(400).json({error:'bad id'})并return,不调用next;合法则调用next()。

fetchUser接受next,从users数组找到匹配项。若用户不存在,则res.status(404).end()并return,避免落入sendUser;存在则把user对象挂到req.user上并next()。最后sendUser直接res.json(req.user)。这样每个阶段只做一件事,逻辑清晰。关键是每个函数都要在决定继续时显式next(),否则链条会中断。通过这种拆分,能精准控制何时终止响应,也方便单独测试某个阶段。

最容易失效的边界条件

第一,回调函数内部发生异步操作后调用next(),但外层同步代码又发响应,容易造成响应重复。例如fs.readFile后回调里res.send,但同时同步路径也可能执行res.send。此时先发的那次设置响应头,第二次会抛Cannot set headers after they are sent。因此异步操作中只要还没到最终响应,就不应提前调用res。

第二,若调用next()但后面没有更多回调,Express会继续查找后续匹配的路由;如果没有则落入默认404处理器。而调用next('route')会跳过当前路由剩余的所有回调,直接去匹配下一条路由。这常用于在某条件下换用另一个处理函数。判断何时使用普通next还是next('route'),取决于你是想继续本路由链,还是想放弃本路由。

回答前,多想一步

容易答错的地方

只有数组能挂多个回调?
实际上独立参数也可,如app.get('/', a,b)同样构成链。数组只是另一种写法,可和独立参数混用。执行顺序仍按出现位置从左到右,不区分数组内外。
调用next()后还能安全res.send
先调next()再发响应是常见的重复发送错误。next()只是移交控制权,不阻止当前函数后续代码继续执行,当前函数仍可能执行res.send()。正确方式是在next()后加return,或使响应函数只出现在链尾。
试着用自己的话回答

面试官还会怎么问?

next('route')和普通next在这条链末尾有什么区别?

普通next()若已到链尾,控制权会去匹配下一个路由;next('route')则是立即跳过当前路由的所有剩余回调,直接匹配下一个路由,即使当前链还有回调也不再执行。

如果第一个回调里故意不调用next也不发响应,会发生什么?

请求会一直挂起,直到客户端超时断开或服务器端配置的超时触发。Express无法自动知道该跳到下一个,这通常属于编码错误,调试时需要检查是否所有路径都调用了next。

多个app.get('/x')和单次挂多个处理函数有何区别?

每次app.get都是独立注册路由。请求匹配时按定义顺序依次检查不同路由,只有当前路由链全部结束(发了响应/next到末尾)才可能到下一路由。单次挂多个处理函数属于同一路由内部,没有外层路由切换语义。

从一道题,走向一组知识

把知识连起来

Express 服务

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

路由多回调与中间件执行顺序共享next推进机制,理解全局中间件顺序有助于对比两者异同。

Express 服务

Express 中调用 next()、next('route') 和 next(err) 分别改变什么控制流?

本题边界涉及next('route')跳转,深入理解next的三种调用情形就能准确区分。

参考资料

  • Routing

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

本题目录
  1. 先记住这个答案
  2. 路由级回调链的流动规则
  3. 一个三段式用户查询场景
  4. 最容易失效的边界条件
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

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

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