最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Global scope for every request in NodeJS Express - Stack Overflow

programmeradmin5浏览0评论

I have a basic express server that needs to store some global variables during each request handling. More in depth, request handling involves many operation that need to be stored in a variable such as global.transaction[]

Of course if I use the global scope, every connection will share information of its transaction and I need a global scope because I need to access the transaction array from many other modules, during my execution.

Any suggestion on this problem? I feel like is something very trivial but I'm looking for complicated solutions :)

Many thanks!

UPDATE This is a case scenario, to be more clear.

On every request I have 3 modules (ModuleA, ModuleB, ModuleC) which read the content of 10 random files in one directory. I want to keep track of the list of file names read by every request, and send back with res.write the list.

So ModuleA/B/C need to access a sort of global variable but the lists of request_1, request_2, request_3 etc... don't have to mix up.

I have a basic express server that needs to store some global variables during each request handling. More in depth, request handling involves many operation that need to be stored in a variable such as global.transaction[]

Of course if I use the global scope, every connection will share information of its transaction and I need a global scope because I need to access the transaction array from many other modules, during my execution.

Any suggestion on this problem? I feel like is something very trivial but I'm looking for complicated solutions :)

Many thanks!

UPDATE This is a case scenario, to be more clear.

On every request I have 3 modules (ModuleA, ModuleB, ModuleC) which read the content of 10 random files in one directory. I want to keep track of the list of file names read by every request, and send back with res.write the list.

So ModuleA/B/C need to access a sort of global variable but the lists of request_1, request_2, request_3 etc... don't have to mix up.

Share Improve this question edited Nov 12, 2013 at 10:18 Leonardo Rossi asked Nov 12, 2013 at 9:50 Leonardo RossiLeonardo Rossi 3,0222 gold badges23 silver badges28 bronze badges 5
  • 1 why is global not meeting your needs? Also, you can use app.locals in express as well (I'm curious as to why it does not meet your requirements)? Ideally one should avoid globals if possible. – ali haider Commented Nov 12, 2013 at 10:00
  • 2 Doesn't it look like this task should be handled by a database? This will also allow your application to scale horizontally, which you can't at the moment because of the need to store everything into one variable that can't be shared among multiple servers. – Paul Mougel Commented Nov 12, 2013 at 10:03
  • I updated the question with a case scenario. I'm not going to use a database at all as this is part of a bigger project and I need to work only with variables in memory. – Leonardo Rossi Commented Nov 12, 2013 at 10:18
  • Could you not keep the name of the files read as local variables in the handling function? – Michael Tang Commented Nov 12, 2013 at 10:36
  • Does this answer your question? Access request context anywhere – Juan Perez Commented Feb 28, 2024 at 0:41
Add a comment  | 

4 Answers 4

Reset to default 14

Here is my suggestion avoid global state like fire.

  • It's the number one maintenance problem in Node servers from my experience.
  • It makes your code not composable and harder to reuse.
  • It creates implicit dependencies in your code - you're never sure which piece depends on which and it's not easy to verify.

You want the parts of code that each piece of an application uses to be as explicit as possible. It's a huge issue.

The issue

We want to synchronize state across multiple requests and act accordingly. This is a very big problem in writing software - some say even the biggest. The importance of the way objects in the application communicate can not be overestimated.

Some solutions

There are several ways to accomplish sharing state across requests or server wide in a Node server. It depends on what you want to do. Here are the two most common imo.

  1. I want to observe what the requests do.
  2. I want one request to do things based on what another request did.

1. I want to observe what the requests do

Again, there are many ways to do this. Here are the two I see most.

Using an event emitter

This way requests emit events. The application reads events the requests fire and learns about them accordingly. The application itself could be an event emitter you can observe from the outside.

You can do something like:

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

And then listen to it from the outside if you choose to.

Using an observer pattern

This is like an event emitter but reversed. You keep a list of dependencies on the request and call a handler method on them yourself when something interesting happens on the request.

Personally, I usually prefer an event emitter because I think they usually solve the case better.

2. I want one request to do things based on what another request did.

This is a lot tricker than just listening. again, there are several approaches here. What they have in common is that we put the sharing in a service

Instead of having global state - each request gets access to a service - for example when you read a file you notify the service and when you want a list of read files - you ask the service. Everything is explicit in the dependency.

The service is not global, only dependencies of it. For example, it can coordinate resources and the data, being some form of Repository).

Nice theory! Now what about my use case?

Here are two options for what I would do in your case. It's far from the only solution.

First option:

  • Each of the modules are an event emitter, whenever they read a file they emit an event.
  • A service listens to all their events and keeps count.
  • Requests have access to that service explicitly and can query it for a list of files.
  • Requests perform writes through the modules themselves and not the added service.

Second option:

  • Create a service that owns a copy of module1, module2 and module3. (composition)
  • The service delegates actions to the modules based on what is required from it.
  • The service keeps the list of files accessed since the requests were made through it.
  • The request stops using the modules directly - uses the service instead.

Both these approaches have advantages and disadvantages. A more complicated solution might be required (those two are in practice pretty simple to do) where the services are abstracted further but I think this is a good start.

One simple way is storing data on the request object.

Here is an example (using Express):

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

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

However, I don't really see how you can need this. When you call moduleA or moduleB, you just have to pass an object as argument, and it solves your issue. Maybe you're looking for dependency injection?

using koa ctx.state doc for this scenario, in express I believe this Plugin should serve your needs.

in order to keep some data that will be resused by another request on the save server app, I propose to use session in expresse and avoid any global state or any props drilling from one request to another.

In order to manage session state in express you could use :

  • session-file-store save the session in a file
  • express-mongodb-session : save the session in mongoDb
  • mssql-session-store -> for a relation db

Of course there is another technique ti manage session in NodeJs.

发布评论

评论列表(0)

  1. 暂无评论