每个HTTP/会话请求的全局数据

GLOBAL data per HTTP/Session request?

本文关键字:全局 数据 请求 会话 HTTP 每个      更新时间:2023-09-26

问题:

是否有任何方法可以在每个会话/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

我的问题是:如果两台不同的计算机向服务器发送请求,那么username的值会独立不同吗?我的意思是,第一个请求处理时的username与第二个请求处理后的username不同,还是它们只是一个变量,将被覆盖?

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

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

将为不同的请求以不同的方式分配username,并且不会相互覆盖。

是的,有一些注意事项。您正在寻找一个称为延续本地存储的模块
这允许您为当前请求的剩余回调保留任意数据,并以全局方式访问它
我在这里写了一篇关于它的博客文章。但要点是:

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

    var createNamespace = require('continuation-local-storage').createNamespace, 
        namespace = createNamespace('myAppNamespace');
    
  3. 创建一个在cls(延续本地存储(命名空间中运行下游功能的中间件

    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. 由于您在namespace.run中运行了next,因此任何下游函数都可以访问名称空间中的数据

    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或绑定到命名空间。

根据请求,我认为您所追求的可以用普通闭包来完成。例如,您可以在采用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();
}; 

这使您可以避免在函数args中乱丢req,并且没有可疑的全局变量。

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

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

假设user1命中了http请求,因此您像这样存储在节点js 中

if(!username)
   username = [];
if(!uniqId)
   uniqId = 0;
uniqId++;
username[uniqId] = 'xyz';

类似于此,它正在运行

您可以使用一个不稳定的功能:nodejs域

我是在头脑中做这件事的,所以阅读文档并弄清楚它是如何工作的;(

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

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

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

var req = process.domain.req;

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

您尝试过使用cookie吗?将cookie设置为浏览器,然后每次有请求时,你就会通过cookie来了解用户。。您可以使用"cookie解析器"节点库。