在Node.js Express中无论在哪里都能访问当前的req对象

21

如果回调函数没有'req'参数,我该如何访问req对象。

情景如下:
在ExpressJs中,我有一个通用的函数,用来处理'req'对象的某些事情,但不将'req'传递给它。

module.exports = {
    get: function(){
        var req = global.currentRequest;
        //do something...
    }
}

目前我的解决方案是编写一个中间件来处理所有的请求,将请求存储在全局变量'req'中,然后我就可以通过'global.currentRequest'在任何地方使用'req'了。

// in app.js
app.use(function (req, res, next) {
    global.currentRequest= req;
    next();
});

但我不知道它是否好? 有人可以提供建议吗?
非常感谢!


除非你真的别无选择,否则请避免使用全局变量。这被认为是一种反模式。参见:http://stackoverflow.com/questions/18635136/why-are-global-variables-considered-bad-practice-node-js - Samuel Toh
2
唯一正确的方法是将 req 作为参数传递给所有需要它的函数。将其存储在全局变量中根本行不通,因为如果任何请求在处理过程中使用异步调用,则可以同时处理多个请求,并且这些多个请求将相互干扰,从而产生难以跟踪的错误。这里没有捷径。将当前请求作为参数传递给需要它的任何代码。 - jfriend00
就像jfriend00所说,这是一个非常糟糕的想法。此外,在Stack上已经讨论了数百次,你不会找到一个合适的解决方案。问题在于你试图将同步思维应用于异步编程。在电影《功夫》中,经常有功夫大师说你必须改变你的思维方式。 - Boris Siscanu
2个回答

18
唯一正确的方法是将req对象作为参数传递给所有需要它的函数。简单地将其放入全局变量中不起作用,因为如果任何请求在其处理中使用异步调用,那么多个请求可以同时进行,这些多个请求会相互干扰,导致难以跟踪的错误。这里没有捷径。将当前请求作为参数传递给需要它的任何代码。在node.js中,您无法将特定于请求的数据放入全局变量中。这样做会为同时进行的两个请求提供机会,从而相互干扰并混淆请求之间的数据。请记住,这是一个可能为许多客户处理请求的服务器。对于服务器,您不能使用同步、一次一个的思维方式。Node.js服务器可能会有很多请求同时飞行,因此普通全局变量不能用于特定于请求的数据。
这里没有捷径。你只能将req对象传递到需要它的函数中。如果这意味着你必须改变几个中间函数的函数签名,那么就这样做吧。这是解决这种类型问题的唯一正确方法。
在某些情况下,您可以使用闭包来“捕获”所需的req对象,然后在不将其传递给这些内部函数的情况下在内部函数中使用它,但这似乎不是您的函数结构。我们必须看到更多实际代码才能知道这是否可能。

#jfriend00 和 @boris-siscanu,你们对这个提交 https://github.com/nodejs/node/commit/9c702922cdcf830cedb92d51e5dc9f956584c3ee 到 nodejs 主分支有什么看法?这是一种针对单线程语言的线程本地存储。这为同步编程语言中已知的新功能打开了大门,例如:依赖注入或更好的日志记录器。 - JRichardsz
@JRichardsz - 这是一种解决类似问题的替代方法。根据我阅读的一些文章,这个概念是可行的,但它存在重大的性能问题,一小部分人希望最终解决这些性能问题,但目前还没有取得太多进展。以下是一些参考资料:线程本地存储async_hooks的性能 - jfriend00

3

实际上,使用类似 全局请求上下文 的东西是可行的。

这是使用 zone.js 实现的,它可以让您在异步任务中持久保存变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接