NodeJS Express中每个请求的全局范围

时间:2013-11-12 09:50:47

标签: javascript node.js express global-variables

我有一个基本的快速服务器,需要在每次请求处理期间存储一些全局变量。 更深入的是,请求处理涉及许多需要存储在global.transaction[]

等变量中的操作

当然,如果我使用global范围,每个连接都将共享其事务的信息,我需要一个全局范围,因为我需要在执行期间从许多其他模块访问事务数组。

有关此问题的任何建议吗?我觉得这是非常微不足道的事情,但我正在寻找复杂的解决方案:)

非常感谢!

更新 这是一种情况,更清楚。

在每个请求中,我有3个模块(ModuleAModuleBModuleC),它们读取一个目录中10个随机文件的内容。我想跟踪每个请求读取的文件名列表,然后发送回res.write列表。

因此ModuleA/B/C需要访问某种全局变量,但request_1request_2request_3等列表不必混淆。

2 个答案:

答案 0 :(得分:10)

以下是我的建议避免火灾等全球状态

  • 根据我的经验,这是Node服务器中的头号维护问题。
  • 它使您的代码无法组合,更难以重用。
  • 它会在您的代码中创建隐式依赖关系 - 您永远无法确定哪个部分取决于哪个部分,并且验证起来不容易。

您希望应用程序的每个部分使用的代码部分尽可能明确 。这是巨大的问题。

问题

我们希望跨多个请求同步状态并采取相应措施。在编写软件时这是一个非常大的问题 - 有人说甚至是最大的问题。不能过高估计应用程序中对象通信方式的重要性。

一些解决方案

有多种方法可以在节点服务器中跨请求或服务器范围实现共享状态。这取决于你想做什么。以下是两种最常见的imo。

  1. 我想观察请求的内容。
  2. 我想要一个请求根据另一个请求做什么。
  3. 1。我想观察请求的作用

    同样,有很多方法可以做到这一点。以下是我最常见的两个。

    使用event emitter

    这种方式请求发出事件。应用程序读取请求触发的事件并相应地了解它们。应用程序本身可以是您可以从外部观察的事件发射器。

    您可以执行以下操作:

    request.emit("Client did something silly",theSillyThing)l
    

    如果您选择,请从外面收听。

    使用观察者模式

    这就像一个事件发射器,但是相反。你在请求中保留一个依赖列表,并在请求发生一些有趣的事情时自己调用一个处理程序方法。

    就个人而言,我通常更喜欢事件发射器,因为我认为通常更好地解决了这个问题。

    2。我想要一个请求根据另一个请求做了什么。

    这不仅仅是倾听,还有很多琐事。再次,这里有几种方法。他们的共同点是我们将共享放在服务

    而不是拥有全局状态 - 每个请求都可以访问服务 - 例如,当您读取文件时通知服务以及何时需要读取文件列表 - 您需要服务。依赖中的一切都是明确的。

    服务不是全局的,只是它的依赖性。例如,它可以协调资源和数据,是某种形式的Repository)。

    好理论!那我的用例呢?

    以下是 I 在您的案例中可以执行的操作的两个选项。它远非唯一的解决方案。

    第一个选项:

    • 每个模块都是一个事件发射器,只要他们读取文件就会发出事件。
    • 服务会监听所有事件并保持计数。
    • 请求可以显式访问该服务,并可以查询它以获取文件列表。
    • 请求通过模块本身执行写操作,而不是添加的服务。

    第二个选项:

    • 创建拥有module1,module2和module3副本的服务。 (组合物)
    • 服务根据需要将操作委托给模块。
    • 该服务保留了自请求通过它访问以来访问的文件列表。
    • 请求停止直接使用模块 - 改为使用服务。

    这两种方法都有优点和缺点。可能需要一个更复杂的解决方案(这两个在实践中非常简单),其中服务进一步抽象,但我认为这是一个良好的开端。

答案 1 :(得分:0)

一种简单的方法是在请求对象上存储数据。

以下是一个示例(使用Express):

app.get('/hello.txt', function(req, res){
    req.transaction = req.transaction || [];

    if (req.transaction.length) {
        // something else has already written to this array
    }
});

但是,我真的不知道你怎么可能需要这个。当您致电moduleAmoduleB时,您只需将对象作为参数传递,它就可以解决您的问题。也许您正在寻找dependency injection