我想从第一个中间件传递一些变量到另一个中间件,我试着这样做,但有“req。有些变量是一个给定的‘未定义’”。


//app.js
..
app.get('/someurl/', middleware1, middleware2)
...

////middleware1
...
some conditions
...
res.somevariable = variable1;
next();
...

////middleware2
...
some conditions
...
variable = req.somevariable;
...

这是因为req和res是两个不同的对象。

您需要在将属性添加到的同一对象上查找该属性。

将变量附加到res.locals对象,而不是req对象。

而不是

req.somevariable = variable1;

有:

res.locals.somevariable = variable1;

正如其他人所指出的,res.locals是通过中间件传递数据的推荐方式。

我不认为最好的做法是传递一个像req.YOUR_VAR这样的变量。您可能需要考虑req.YOUR_APP_NAME。YOUR_VAR或req.mw_params.YOUR_VAR。

它将帮助您避免覆盖其他属性。

v4。x API文档

这就是res.locals对象的作用。不支持直接在请求对象上设置变量,也没有相关文档。locals保证在请求的整个生命周期内保持状态。

引用文件:

对象,其中包含作用域为的响应局部变量 请求,因此仅对期间呈现的视图可用 请求/响应周期(如果有的话)。否则,这个属性为 和app。locals一样。 此属性对于公开请求级信息非常有用,例如 请求路径名、经过身份验证的用户、用户设置,等等。

app.use(function(req, res, next) {
    res.locals.user = req.user;  
    res.locals.authenticated = !req.user.anonymous;
    next();
});

在下一个中间件中检索变量:

app.use(function(req, res, next) {
    if (res.locals.authenticated) {
        console.log(res.locals.user.id);
    }
    next();
});

诀窍很简单……请求周期仍然存在。您只需添加一个新变量,它将创建一个临时的调用

app.get('some/url/endpoint', middleware1, middleware2);

因为您可以在第一个中间件中处理请求

(req, res, next) => {
    var yourvalue = anyvalue
}

在中间件1中,你可以像下面这样处理你的逻辑并存储你的值:

req.anyvariable = yourvalue

在中间件2中,你可以通过以下方法从中间件1中获取这个值:

(req, res, next) => {
    var storedvalue = req.yourvalue
}

如上所述,res.locals是一种很好的(推荐的)方法。请参阅这里的快速教程,了解如何在Express中做到这一点。

将变量传递给其他中间件和端点函数的最常见模式是将值附加到请求对象req。

在你的例子中,这意味着有这样的中间件:

app.use(function (req, res, next) {
  req.someVariable = 123;
  next();
});

app.use(function (req, res, next) {
  console.log("The variable is", req.someVariable);
  next();
});

此模式有许多常见的用例,并且它是在express社区中执行此操作的标准方式。例如:

表达。Json,它随express一起提供,它以前是body解析器的一部分,对所有请求解析都遵循相同的模式。 Multer用于解析多部分数据 express-jwt Express-validator(见代码) express-session express-useragent express-pino-logger express-bunyan-logger


值得注意的是,目前投票最多的答案错误地建议使用res.locals——这似乎源于对文档的误读。出于这个原因,我将详细说明为什么这不是解决问题的通常方法(尽管它也不是特别有害)。

的文档

为了支持res.locals方法适合该案例,引用了现已过时的文档:

一个包含响应局部变量的对象,其作用域为请求,因此仅对在请求/响应周期(如果有的话)期间呈现的视图可用。否则,此属性与app.locals相同。 此属性对于公开请求级信息(如请求路径名称、经过身份验证的用户、用户设置等)非常有用。

注意这里的框架:res.locals是仅对“在请求期间呈现的视图”可用的变量(强调添加)。

这就是res.locals所涉及的。render渲染一些模板文件,其中包含一些给定的数据以及对局部变量的访问。实际上,这在v2文档中更清楚,我们现在更新了当前的Express文档,使其更清楚:

Use this property to set variables accessible in templates rendered with res.render. The variables set on res.locals are available within a single request-response cycle, and will not be shared between requests. In order to keep local variables for use in template rendering between requests, use app.locals instead. This property is useful for exposing request-level information such as the request path name, authenticated user, user settings, and so on to templates rendered within the application.

(强调)。

该指南

关于扩展req作为标准方法的进一步证据可以在编写中间件指南中找到,该指南指出:

接下来,我们将创建一个名为“requestTime”的中间件函数,并向请求对象添加一个名为requestTime的属性。 const requestTime = function (req, res, next) { 要求的事情。requestTime = Date.now() next () }

当我们在回答这个问题的讨论中提到这一点时,一个用户回答说:“在他们添加res.locals之前,这就是你的做法,所以可能是旧文档。Res.locals是一个专门用于此的命名空间。”

然而,这与代码库的历史并不一致:局部变量从v2开始就存在了,这比例如express要早得多。Json被包含在库中,在这一点上,如果在res.locals中保存值确实正确,那么改变行为是有意义的。

关闭笔记

大喊@real_ate谁写了评论,但被忽略了。