每个HTTP /会话请求的GLOBAL数据?

cuz*_*AZN 5 javascript global request node.js express

题:

有没有办法在每个session/http请求中创建一个变量存储?该变量必须是全局可访问的,并且每个HTTP请求/连接/会话不同,并且不需要从一个函数传递给另一个函数.

例如(仅用于说明):

setVariableThatCanBeAccessedByThisHTTPRequestOnly( 'a string data' );
Run Code Online (Sandbox Code Playgroud)

任何事都应该有效,但我宁愿远离将它从功能转移到功能.

//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 );

};
Run Code Online (Sandbox Code Playgroud)

原始问题

我最近一直在玩node.js,对它的GLOBAL范围有点关注.假设我们有一个server.js文件:

username = ""; //Global scope
Run Code Online (Sandbox Code Playgroud)

然后,当建立连接并且服务器收到请求时,它将执行以下操作:

username = selectUsernameWithConditions(); //This will return a username
Run Code Online (Sandbox Code Playgroud)

我的问题是:如果有两台不同的计算机将请求发送到服务器,那么值是否username会独立地不同?我的意思是,username处理第一个请求的时间与处理username第二个请求的时间不同,或者它们只是一个变量并且将被覆盖?

如果它们被覆盖,那么存储数据并使它们仅在该请求和/或会话中可以全局访问的最佳方式是什么?例如,以下代码:

username = selectUsernameWithConditions(); //This will return a username
Run Code Online (Sandbox Code Playgroud)

username针对不同的请求进行不同的分配,而不是相互覆盖.

iba*_*ash 5

是的,有一些警告。您正在寻找一个名为continuation-local-storage的模块。
这允许您为当前请求的其余回调保留任意数据,并以全局方式访问它。
在这里写了一篇关于它的博客文章。但要点是这样的:

  1. 安装 cls: npm install --save continuation-local-storage
  2. 为您的应用程序创建一个命名空间(在您的应用程序主文件的顶部)

    var createNamespace = require('continuation-local-storage').createNamespace, 
        namespace = createNamespace('myAppNamespace');
    
    Run Code Online (Sandbox Code Playgroud)
  3. 创建一个在 cls (continuation-local-storage) 命名空间中运行下游函数的中间件

    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();
      });
    });
    
    Run Code Online (Sandbox Code Playgroud)
  4. 由于您在next内运行namespace.run,因此任何下游函数都可以访问命名空间中的数据

    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'
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 需要注意的是,某些模块可能会“丢失”由 cls 创建的上下文。这意味着当你在命名空间上查找 'foo' 时,它不会有它。有几种方法可以解决这个问题,即使用另一个模块,如cls-redis、 cls-q 或绑定到命名空间。