20

I wonder how to access req object if there's no 'req' parameter in callback.

This is the scenario:
In ExpressJs, I have a common function, it uses to handle something with 'req' object, but not pass req into it.

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

My current solution is that I write a middleware for all request, I put the 'req' in global variable, then I can access the 'req' everywhere with 'global.currentRequest'.

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

But I don't know if it's good? Can anyone have suggestions?
Thanks a lot!

Sky
  • 231
  • 1
  • 2
  • 5
  • Avoid using global variables unless you are really left without a choice. It is considered to be an anti-pattern. See: http://stackoverflow.com/questions/18635136/why-are-global-variables-considered-bad-practice-node-js – Samuel Toh Sep 06 '16 at 03:40
  • 2
    The only proper way is to pass the `req` through as an argument to all functions that need it. Stashing it in a global simply will not work because multiple requests can be in process at the same time if any requests use async calls as part of their processing and those multiple requests will stomp on each other making a hard to track down bug. There are no shortcuts here. Pass the current request as an argument to any code that needs it. – jfriend00 Sep 06 '16 at 04:07
  • like jfriend00 wrote it's a really bad idea. Also, it was discussed hundreds of time on stack and you will not find a proper solution. The problem is that you try to apply sync thinking for async programming. Often in movie Kungfu master says that you have to change your way of thinking. – Boris Siscanu Sep 06 '16 at 06:48

2 Answers2

18

The only proper way is to pass the req object through as an argument to all functions that need it.

Stashing it in a global simply will not work because multiple requests can be in process at the same time if any requests use async calls as part of their processing and those multiple requests will stomp on each other making a hard to track down bug. There are no shortcuts here. Pass the current request as an argument to any code that needs it.

You cannot put request-specific data into a global in node.js, ever. Doing so will create an opportunity for two requests that are in-flight at the same time to stomp on each other and for data to get confused between requests. Remember, this is a server that is potentially handling requests for many clients. You cannot use synchronous, one-at-a-time thinking for a server. A node.js server may potentially have many requests all in flight at the same time and thus plain globals cannot be used for request-specific data.

There is no shortcut here. You will just have to pass the req object through to the function that needs it. If that means you have to change the function signature of several intervening functions, then so-be-it. That's what you have to do. That is the only correct way to solve this type of problem.

There are some circumstances where you may be able to use a closure to "capture" the desired req object and then use it in inner functions without passing it to those inner functions, but it does not sound like that is your function structure. We'd have to see a lot more of your real/actual code to be able to know whether that's a possibility or not.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • #jfriend00 and @boris-siscanu what do you think about this commit https://github.com/nodejs/node/commit/9c702922cdcf830cedb92d51e5dc9f956584c3ee to the nodejs master branch ? Is a kind of **Thread Local Storage** for a single thread language. This opens new functionalities well known in sync programming languages like : dependency injection or better loggers. – JRichardsz Mar 04 '20 at 17:01
  • @JRichardsz - That is an effort to make an alternate way of solving issues like this. According to a few articles I've read, the concept works, but it's got significant performance issues and a small group of people would like to eventually solve those performance issues, but have not really made much progress yet. Here are a couple references: [Thread Local storage](https://medium.com/trabe/continuation-local-storage-for-easy-context-passing-in-node-js-2461c2120284) and [Performance of async_hooks](https://github.com/nodejs/benchmarking/issues/181). – jfriend00 Mar 04 '20 at 18:42
3

Actually, this is possible with something like global-request-context

This is using zone.js which let you persist variables across async tasks.

Tom Esterez
  • 21,567
  • 8
  • 39
  • 44