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

时间:2014-08-06 03:52:58

标签: javascript node.js express request global

问题:

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

例如(仅举例说明):

setVariableThatCanBeAccessedByThisHTTPRequestOnly( 'a string data' );

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

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

};

原始问题

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

username = ""; //Global scope

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

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

我的问题是:如果有2台不同的计算机将请求发送到服务器,username的值是否会独立地不同?我的意思是,处理第一个请求时username处理第二个请求时usernameusername = selectUsernameWithConditions(); //This will return a username 不同,或者它们只是一个变量会被覆盖吗?

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

username

将为不同的请求分配{{1}},而不是相互覆盖。

5 个答案:

答案 0 :(得分:4)

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

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

    var createNamespace = require('continuation-local-storage').createNamespace, 
        namespace = createNamespace('myAppNamespace');
    
  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();
      });
    });
    
  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'
    }
    
  5. 有一点需要注意,某些模块可能“失去”cls创建的上下文。这意味着当您在命名空间中查找“foo”时,它将不会拥有它。有几种方法可以解决这个问题,即使用另一个模块,如cls-redis,cls-q或绑定到命名空间。

答案 1 :(得分:1)

您可以使用不稳定的功能:nodejs domains

我在我的头顶做这个,所以阅读文档并弄清楚它是如何工作的;)

在层次结构中创建一个中间件,它将创建一个域并在该域的上下文中运行剩余的请求处理程序:

app.use(function(req, res, next) {
  var domain = domain.create();
  domain.req = req;
  domain.run(next);
});

然后在处理程序的任何位置,您都可以使用以下命令访问当前请求:

var req = process.domain.req;

再次阅读文档,我真的不确定这一切,但这是一种方法!

答案 2 :(得分:1)

根据请求,我认为您之后可以使用普通的闭包来完成。例如,您在模块中定义了带有req参数的自定义函数:

util_funcs.js:

module.exports = function( req ){
  return {
    customFunctionThatRequiresReq: function(){ console.info( req ) },
    otherFunctionThatRequiresReq:  function(){ console.log( req ) }
  };
};

然后,只要您依赖这些功能(可能是应用程序中其他地方的某些中间件),您就可以在上下文中要求它们:

var someMiddleWare = function( req, res, next ){

  var utils = require( 'util_funcs.js' )( req );

  utils.customFunctionThatRequiresReq();
  utils.otherFunctionThatRequiresReq();

}; 

这样可以避免使用req乱丢你的函数args,也不会丢弃可疑的全局变量。

答案 3 :(得分:0)

如果我理解你的问题,你可以尝试在节点js中创建可以存储用户名的全局变量

您可以使用具有唯一ID的全局数组

假设user1点击http请求,因此您在节点js

中存储如此
if(!username)
   username = [];

if(!uniqId)
   uniqId = 0;
uniqId++;

username[uniqId] = 'xyz';
像这样的类似工作

答案 4 :(得分:0)

你尝试过用饼干吗? 将cookie设置为浏览器,然后每次有请求时,您都会通过其cookie了解用户。 你可以使用'cookie-parser'节点库。