【问题标题】:Does res.send() in an Express JS handler automatically call next()?Express JS 处理程序中的 res.send() 是否会自动调用 next()?
【发布时间】:2018-12-04 18:04:06
【问题描述】:

我知道一个可以在 ExpressJS 处理程序中在 res.send 之后调用 next,但在任何情况下 res.send 是否“自动”调用 next

我有以下代码

const express = require('express');

var app = express();

app.get('/', (req, res, next) => {
  console.log('in route handler')
  res.send('Hello World')
});

app.use((req,res, next) => {
  console.log('in middleware')
  console.log('...........')
})

app.listen(process.env.PORT || 8080)

我的控制台日志是

in route handler
in middleware
...........

如果我确实在res.send 之后明确调用next,我会得到

in route handler
in middleware
...........
in middleware
...........

因此看起来中间件被调用了两次。

这是为什么?是因为中间件也以某种方式“直接”调用,而不管路由如何?也就是说,它只是 always 被调用,即使它在路由处理程序之后?但我想如果是在路由处理程序之后,要到达中间件,它前面的路由处理程序必须调用next,就像这里的https://derickbailey.com/2016/05/09/in-what-order-does-my-express-js-middleware-execute/,它说“事实证明,添加中间件的顺序很重要. 并且由于第二个 'use' 方法是在 'get' 处理程序之后添加的,因此它永远不会被调用。'get' 处理程序在呈现页面时会短路中间件,从而阻止处理任何进一步的中间件。”

Express 版本 4.16.0,Node 版本 11.2.0

感谢您的澄清!

【问题讨论】:

  • 好像和火狐有关——我用火狐测试过,结果如上。今天我使用 Chrome 进行了测试,结果“符合预期”,即如果您在发送一个中间件后没有调用next,则不会调用下一个。

标签: node.js express middleware


【解决方案1】:

这是为什么?

这是因为浏览器发送了一个额外的请求来获取favicon;当您转到localhost:8080 chrome(或 firefox)时,会向/ 发送get 请求,因此您的服务器会匹配此路由并记录:

in route handler

之后它立即向/favicon.ico 发送第二个get 请求,但您的服务器不匹配任何路由。它在路由和日志之后继续安装中间件:

in middleware
...........

当然,通过调用next(),您已经在上述两个请求之后显式调用了您的中间件,因此:

in route handler
in middleware
...........
in middleware
...........

但我想如果是在路由处理程序之后,到达 中间件,它前面的路由处理程序必须调用下一个

你当然是对的。将serve-favicon 中间件添加到您的应用程序中,并且您的自定义中间件在没有明确调用next() 的情况下永远不会被调用,除非没有任何路由不匹配:

const express = require('express');
var favicon = require('serve-favicon')
var path = require('path')

var app = express()
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))

app.get('/', (req, res, next) => {
  console.log('in route handler')
  res.send('Hello World')
});

app.use((req,res, next) => {
  console.log('in middleware')
  console.log('...........')
})

app.listen(process.env.PORT || 8080)

顺便说一下,在所有路由之后安装的中间件是处理 404 的合适位置,因为如果我们到了这一点,我们的应用程序路由都没有匹配。

【讨论】:

    【解决方案2】:

    app.use() 中间件允许你有一组你的路由应该遵循的动作。假设您的所有路由在实际执行该路由的指定操作之前都会进行一些处理。

    当我运行您的代码时,它打印在下面,Hello World 在 Mozilla(版本 63.0.3(64 位))和 Chrome(版本 71.0.3578.80)中呈现

    在中间件中的路由处理......

    res.send() 现在来回答你的问题,没有必要在调用 res.send() 之后调用 next() 。因为一旦遇到它,它会立即发送响应。是的,您是正确的,中间件的顺序确实很重要。因此,当您在 res.send() 之后添加 next() 时,执行了以下操作:

    1. 首先“/”路由将在浏览器停止加载时返回 Hello World
    2. 您的中间件将被调用两次,一次是由于 next() 而第二次是由于中间件本身。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-31
      • 2020-06-19
      • 2017-03-27
      • 2014-11-07
      • 1970-01-01
      相关资源
      最近更新 更多