Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GLOBAL data per HTTP/Session request?

QUESTION:

Is there any way to create a variable storage in per session/http request? The variable must be globally accessible and different per HTTP request/connection/session, and need not be passed from function to function.

For example (just to illustrate):

setVariableThatCanBeAccessedByThisHTTPRequestOnly( 'a string data' );

Anything should work, but I'd prefer to stay away from passing it from function to function.

//I'm trying to get rid of passing req parameter to all custom functions.
//I'd like to store it in a variable somehow, that it can be accessed globally, but only within that session/request.
exports.functionName = function( req, res ) {

   customFunctionThatRequiresReq( req );

};

ORIGINAL QUESTIONS

I've been playing with node.js lately, and have a little concern about its GLOBAL scope. Let's say we have a server.js file:

username = ""; //Global scope

Then when a connection is established and the server receives a request, it will do the followings:

username = selectUsernameWithConditions(); //This will return a username

My question is: If 2 different computers are sending the requests to the server, will the value of username be independently different? I mean, does the username when the first request is processed different from the username when the second request is processed, or they are just one variable and will be overridden?

If they are overridden, what is the best way to store data and make them globally accessible within that requests and/or session only? For example, the following code:

username = selectUsernameWithConditions(); //This will return a username

Will assign username differently for different requests and not overriding each other.

like image 706
cuzmAZN Avatar asked Aug 06 '14 03:08

cuzmAZN


People also ask

Is it bad to use global variables in JavaScript?

Avoid globals. Global variables and function names are an incredibly bad idea. The reason is that every JavaScript file included in the page runs in the same scope.

Are there global variables in JS?

In JavaScript, there's always a global object defined. In a web browser, when scripts create global variables defined with the var keyword, they're created as members of the global object. (In Node.

What are the 3 ways a global variable is created JavaScript?

Variables can be declared by var, let, and const keywords. Before ES6 there is only a var keyword available to declare a JavaScript variable.


1 Answers

Yes, with some caveats. You're looking for a module called continuation-local-storage.
This allows you to keep arbitrary data for the remainder of callbacks for the current request, and access it in a global fashion.
I wrote a blog post about it here. But the gist is this:

  1. Install cls: npm install --save continuation-local-storage
  2. Create a namespace for your app (at the top of the main file for your app)

    var createNamespace = require('continuation-local-storage').createNamespace, 
        namespace = createNamespace('myAppNamespace');
    
  3. Create a middleware that runs downstream functions in the cls (continuation-local-storage) namespace

    var getNamespace = require('continuation-local-storage').getNamespace,
        namespace = getNamespace('myAppNamespace'),
    
    app.use(function(req, res, next) {    
      // wrap the events from request and response
      namespace.bindEmitter(req);
      namespace.bindEmitter(res);
    
      // run following middleware in the scope of the namespace we created
      namespace.run(function() {
        namespace.set(‘foo’, 'a string data');
        next();
      });
    });
    
  4. Since you ran next within namespace.run, any downstream function can access data in the namespace

    var getNamespace = require('continuation-local-storage').getNamespace,
        namespace = getNamespace('myAppNamespace');
    
    // Some downstream function that doesn't have access to req...
    function doSomething() {
      var myData = namespace.get('foo');
      // myData will be 'a string data'
    }
    
  5. There is the caveat that certain modules can "lose" the context created by cls. This means that when you go to lookup 'foo' on the namespace, it won't have it. There are a few ways to deal with this, namely using another module like cls-redis, cls-q, or binding to the namespace.

like image 87
ibash Avatar answered Oct 04 '22 16:10

ibash