问题:
有没有办法在每个会话/ 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
处理第二个请求时username
与username = selectUsernameWithConditions(); //This will return a username
不同,或者它们只是一个变量会被覆盖吗?
如果它们被覆盖,那么在该请求和/或会话中存储数据并使其全局可访问的最佳方法是什么?例如,以下代码:
username
将为不同的请求分配{{1}},而不是相互覆盖。
答案 0 :(得分:4)
是的,有一些警告。 您正在寻找名为continuation-local-storage的模块 这允许您为当前请求保留剩余回调的任意数据,并以全局方式访问它 我写了一篇关于它的博客文章here。但要点是:
npm install --save continuation-local-storage
为您的应用创建一个命名空间(位于应用主文件的顶部)
var createNamespace = require('continuation-local-storage').createNamespace,
namespace = createNamespace('myAppNamespace');
创建一个在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();
});
});
由于您在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'
}
有一点需要注意,某些模块可能“失去”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)