ExpressJS调用next()时如何确定后续执行的中间件与方法
Express 中
next()的执行规则判定逻辑 核心结论:所有中间件、路由处理函数的执行顺序,严格按照其在源码中被注册的先后顺序排列,next()本身不做智能路由调度,仅顺着注册队列向后查找下一个匹配项执行。
具体规则如下:
- Express 服务启动时,会将所有通过
app.use()、app.get()/app.post()等方法注册的中间件、路由处理函数,按照代码书写的先后顺序,存入一个线性的执行队列。 - 请求进入服务后,会从队列头部开始逐项匹配校验:
- 无路径的通用中间件默认匹配所有请求;带路径前缀的中间件匹配符合路径前缀规则的请求
- 路由处理函数需要同时满足「HTTP方法一致」「请求路径匹配路由规则」两个条件才算命中
- 你看到的3个签名完全一致的
app.get('/user/:id', function (req, res, next) {}),本质是给同一路由规则按注册顺序绑定了3个串行的路由级处理函数,天然属于同一条执行链。 - 当你在当前处理函数中调用
next()时,Express会从当前执行位置的下一个队列项开始,继续向后查找第一个匹配当前请求的处理函数/中间件,找到后立即执行,后续队列项暂时搁置;如果当前函数没有调用next(),队列后续的所有匹配项都不会被执行,若未主动返回响应则请求会挂起超时。 - 特殊情况:如果调用
next()时传入了错误参数,比如next(new Error('报错')),Express会跳过队列中所有普通处理函数,直接查找后续注册的错误处理中间件(签名为4个参数:(err, req, res, next))执行。
注意:执行顺序完全和注册顺序绑定,如果把需要前置执行的逻辑(比如鉴权、日志、参数校验)写在业务路由后面,且前置逻辑前的路由没有调用
next(),这些前置逻辑会完全失效。
举个直观的代码示例:
// 第一个注册的/user/:id路由处理函数 app.get('/user/:id', (req, res, next) => { console.log('执行第一个处理函数') req.userId = req.params.id next() // 触发向后查找下一个匹配项 }) // 第二个注册的/user/:id路由处理函数 app.get('/user/:id', (req, res) => { console.log('执行第二个处理函数') res.send(`当前访问用户ID:${req.userId}`) // 这里没有调用next,后续的匹配项不会执行 }) // 第三个注册的/user/:id路由处理函数 app.get('/user/:id', () => { console.log('第三个处理函数永远不会被执行') })
当请求GET /user/123时,控制台只会打印前两条日志,第三个处理函数不会被触发。
内容的提问来源于stack exchange,提问作者RandomCoder
相关产品推荐
相关产品推荐

