在Express.js中使用next()将变量传递到下一个中​​间件


200

好吧,我的问题是我想将一些变量从第一个中间件传递给另一个中间件,我尝试这样做,但是有req.somevariable一个“给定为'undefined'”。


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

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

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

应该管用。除非这是一个错字,否则您可能会失败,因为您res在Middleware1 中将值分配给了它并尝试从reqMiddleware2中获取了它。
Andreas Hultgren

感谢z @AndreasHultgren
user2791897 2013年

Local variables are available in middleware via req.app.locals expressjs.com/pt-br/api.html#app.locals
罗尼·罗斯顿

Answers:


202

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

代替

res.somevariable = variable1;

有:

req.somevariable = variable1;

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


13
使用res.locals.variable = var; 看到其他答案
Godzsa

1
要检索变量,请在下一个中间件功能中使用req.res.locals.variable
William Wu,

3
@WilliamWu res.locals,不是req.res.locals
cchamberlain

2
res.locals.myVar是要走的路。
jasonseminara

447

这就是res.locals对象的用途。不支持也不记录直接在请求对象上设置变量。保证res.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();
});

66
不知道为什么这不是可接受的答案,这是整个请求中从中间件设置变量记录方法。
山姆·霍姆斯

11
res.locals旨在供在请求生命周期中最终呈现的视图使用,这就是文档所说的。如果您不使用视图,则将东西放在locals对象上是过大的做法,这不是惯例。在这种情况下,我倾向于鼓励人们遵守约定,以便我们在学习Express或请求生命周期之类的概念时可以减少认知负担。
real_ate

2
@real_ate是res.locals的主要用法,但是没有解决OP的问题。将请求范围的变量传递给将来的中间件有时是必要的,我遇到的时间通常是围绕早期中间件中的用户身份验证进行的,该中间件设置了要在下游中间件中路由的声明。
cchamberlain

14
用于编写中间件的快速文档在req对象expressjs.com/en/guide/writing-middleware.html上设置了变量。看看本节Middleware function requestTime
fish鱼

2
@goonerify多数民众赞成在那不是响应如何工作。响应通过调用响应对象的功能特性,例如传输res.json({})res.locals是仅在后端在所述请求的寿命可用。 expressjs.com/en/5x/api.html
cchamberlain

22

我认为最佳做法不会传递类似的变量req.YOUR_VAR。您可能要考虑req.YOUR_APP_NAME.YOUR_VARreq.mw_params.YOUR_VAR

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

2020年5月31日更新

res.locals是您要寻找的对象,该对象的作用域是请求。

一个对象,该对象包含范围为请求的响应局部变量,因此仅可用于在该请求/响应周期(如果有)中呈现的视图。否则,此属性与app.locals相同。

此属性对于公开请求级别的信息很有用,例如请求路径名,经过身份验证的用户,用户设置等。


2
您如何建议req.YOUR_APP_NAME = {}初始设置?您只是尝试写信,req.YOUR_APP_NAME.someVar否则将得到一个req.YOUR_APP_NAME尚未定义的错误。
沙2015年

2
@Kousha您可以在路由脚本的顶部编写路由器中间件:router.use(function(req,res,next){req.YOUR_APP_NAME = {};next()})
Tomas

有没有办法通过next()函数将其作为参数传递?像next(myObj)
philx_x

1
@Kousha-您的未定义错误与express无关,它试图将属性分配给不存在的对象。通常,您可以使用req.APP_NS = req.APP_NS || {}; req.APP_NS.somevar = 'value'
cchamberlain

1
@philx_x,如果将任何参数传递给next函数,它将触发express'错误处理程序并退出。检查文档。
Merl

7

那是因为reqres是两个不同的对象。

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


3

诀窍很简单...请求周期仍然很活跃。您只需添加一个新变量即可创建一个临时变量,

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
}

1

如上所述,res.locals是一种很好的方法(推荐)。有关如何在Express中执行此操作的快速教程,请参见此处

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.