在当前的项目(一种商店系统)中,我使用带有 expressJS 和 connect-mongo 的 node.js 作为 session 存储。在客户端,我在启动时使用单个请求来创建一个新 session ,然后将多个并行请求发送到 node.js 服务器。 因为这些并行请求会更改 session ,所以这些更改似乎会相互覆盖,尽管它们当然会更改 session 的不同对象。
示例(所有 3 个请求同时启动):
req.session.productHist['abc']req.session.productHist['def']因为请求 C 在请求 A 和 B 之后完成,但在它们完成之前开始,所以它似乎用请求 C 开始时保持的值(null)覆盖了 session.productHist。
我该如何解决这个问题?
更新:
一些带有控制台输出的示例代码:
var url = require('url'),
express = require('express'),
MongoStore = require('connect-mongo');
var aDay = 24*60*60*1000;
var app = express.createServer();
app.configure(function(){
app.use(express.cookieParser());
app.use(express.session({
secret: "secret",
store: new MongoStore({ db: 'lmsCache' }),
maxAge: aDay
})
);
app.use(express.methodOverride()); app.use(express.bodyParser());
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
app.use(app.router);
app.use(express.logger());
});
function sendStringified(req, res, data) {
data = JSON.stringify(data);
if (req.url_query.callback) { data = req.url_query.callback + "(" + data + ");"; }
res.send(data);
}
function parseParams(req,res,next) {
req.url_query = url.parse(req.url,true).query;
next();
}
function doExpensiveStuff(req,res,next) {
console.log("######################### init start");
[...]
}
app.get('/init', parseParams, doExpensiveStuff, function(req,res) {
console.log("init: session.productHist: " + JSON.stringify(req.session.productHist));
console.log("######################### init end");
sendStringified(req,res,null);
});
app.get('/products', parseParams, function(req,res) {
console.log("######################### products "+req.url_query.category+" start");
if(!req.session.productHist[req.url_query.category])
req.session.productHist[req.url_query.category] = [];
for(var i=0;i<2;i++) {
req.session.productHist[req.url_query.category].push({ "id": new Date().toGMTString() });
}
console.log("products: session.productHist: " + JSON.stringify(req.session.productHist));
console.log("######################### products "+req.url_query.category+" end");
sendStringified(req,res,[]);
});
app.get('/newSession', parseParams, function(req,res) {
console.log("######################### newSession");
req.session.productHist = {};
sendStringified(req,res,true);
});
app.listen(8080);
time = new Date().toGMTString();
console.log('Server starting at: ' + time);
控制台日志:
Server starting at: Thu, 15 Dec 2011 15:50:37 GMT
################### newSession
################### init start
################### products -1 startproducts: session.productHist: {"-1":[{"id":"Thu, 15 Dec 2011 15:50:40 GMT"},{"id":"Thu, 15 Dec 2011 15:50:40 GMT"}]}
################### products -1 end################### init end
init: session.productHist: {}
################### products -1 start
[...]
products: session.productHist: {"-1":[{"id":"Thu, 15 Dec 2011 15:50:53 GMT"},{"id":"Thu, 15 Dec 2011 15:50:53 GMT"}]}
################### products -1 end
最佳答案
我想我已经找到了这个棘手问题的答案。
来自 Express.js文档:
req.session 上的属性会自动保存在响应中
短版
当您设置 session 变量 (req.session.my_var = value) 时,它实际上并没有被保存(当时),而是稍后(当您发送响应时,在您的情况下)当你执行 res.send 时)。这导致了你的问题。
加长版
那么这到底是什么意思?
关于session - 对 node.js、connect-mongo、 session 覆盖的并行请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8507278/
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)
在Ruby类中,我重写了三个方法,并且在每个方法中,我基本上做同样的事情:classExampleClassdefconfirmation_required?is_allowed&&superenddefpostpone_email_change?is_allowed&&superenddefreconfirmation_required?is_allowed&&superendend有更简洁的语法吗?如何缩短代码? 最佳答案 如何使用别名?classExampleClassdefconfirmation_required?is_a
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
使用rails4,ruby2。我在rails配置中为我的cookiesession设置了30分钟的超时时间。问题是,如果我转到表单,让session超时,然后提交表单,我会收到此ActionController::InvalidAuthenticityToken错误。如何在Rails中优雅地处理这个错误?比如说,重定向到登录屏幕? 最佳答案 在您的ApplicationController:rescue_fromActionController::InvalidAuthenticityTokendoredirect_tosome_p
我明白了:x,(y,z)=1,*[2,3]x#=>1y#=>2z#=>nil我想知道为什么z的值为nil。 最佳答案 x,(y,z)=1,*[2,3]右侧的splat*是内联扩展的,所以它等同于:x,(y,z)=1,2,3左边带括号的列表被视为嵌套赋值,所以它等价于:x=1y,z=23被丢弃,而z被分配给nil。 关于ruby-带括号和splat运算符的并行赋值,我们在StackOverflow上找到一个类似的问题: https://stackoverflow
我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于
假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje