【发布时间】:2013-03-23 22:12:30
【问题描述】:
我有一个 Node.js HTTP 服务器正在运行,如下所示(简化):
http = require('http');
help = require('./modules/help').run;
router = require('./modules/router').run;
m = {something: require('./modules/something')};
var server = http.createServer(router).listen(8001);
“help”是一组functions-helpers,例如:
module.exports.run = {
joinObjects: function(obj1, obj2) {
for (var prop in obj2) {
obj1[prop] = obj2[prop];
}
return obj1;
}
}
“路由器”处理请求(进一步向下传递并处理对客户端的响应):
module.exports.run = function(req, res) {
var urlPath = url.parse(req.url).pathname;
switch(urlPath) {
case '/something':
requestHandler(req, res, 'something');
break;
...
}
function requestHandler(req, res, handler) {
var data = '';
req.on('data', function(chunk) {
data += chunk;
}
req.on('end', function() {
m[handler].run(req, data, function(response) {
response.headers = help.joinObjects(config.responseHeaders, response.headers);
res.writeHead(response.code, response.headers);
res.end(response.data);
});
}
}
}
“处理程序”模块/函数运行回调函数并将响应(代码、标头和数据)传递给它。然后回调函数将标头与配置文件中设置的一组默认标头合并。
问题:当有两个连接同时调用help.joinObjects()(这是我的猜测)时,response.headers 属性与另一个用户/连接中的一个发生冲突并返回错误数据。如果我注释掉进行合并的行,则不会发生这种情况。
问题:我的“帮助”模块有什么问题?这里有一些我不明白的范围问题。
【问题讨论】:
-
可能是因为您将响应中的标头合并到配置中?将
help.joinObjects(config.responseHeaders, response.headers);更改为help.joinObjects(response.headers, config.responseHeaders);是否可以解决您的问题? -
嘿!不,这不是问题。最后的
headers属性包含应该发送回一个完全不同的客户端的标头(可怕!)。它们不是来自配置文件。问题在于,一些本应是客户端唯一的数据实际上是由碰巧同时发送请求的两个(或多个)客户端共享的。我认为所有的东西都封装得很好,不会在不同的连接之间共享,但事实证明它不是?.. -
但是js是单线程运行的,所以没有竞态条件。你确定我的建议没有帮助吗? (抱歉再次问:))
-
我无法通过您的修复重现该问题,而我的版本仍然存在该问题。因此,您的建议可能已经解决或隐藏了问题,但问题是 - 如何?.. 在某些时候,两个不同的用户连接必须访问相同的范围,因为
config.responseHeaders和response.headers都不包含我可以检测到的标头返回时在我的浏览器中。并且该特定标头是从我当时未访问的单独模块返回的。所以我很确定代码中存在范围问题。 -
好的,知道了! config 在全局(或顶部,无关紧要)中,并且由于 JavaScript 通过引用传递变量,因此我的 joinObjects 函数在每次调用时都会修改全局对象的属性(即 - config 属性)。我的坏:(
标签: javascript node.js scope