我有这个问题只有当我尝试刷新页面而我无法解决时,我尝试了一切但仍然发生了同样的事情。当我在项目中添加socket.io时,它开始发生了。该项目在多个服务器中运行,这些服务器通过套接字相互连接。
测试案例:当我渲染页面时,第一次一切顺利但是,如果我刷新同一页面,我会收到此错误:
错误:"错误:发送后无法设置标头。在ServerResponse.OutgoingMessage.setHeader(_http_outgoing.js:344:11)"
注意:当进入IF()并发送"返回res.end('激活码是无效的!');"它没事了!我刷新它并刷新它,一切顺利。我的问题在于RENDER。
我的代码如下:
activationUser = function(req,res,next){
var data = {
activationCode : req.params.activationCode,
now : new Date().valueOf(),
ip : req.connection.remoteAddress,
fId : frontalId
}
socketCore.emit('activationUser', data);
socketCore.on(frontalId + 'activationUserResp', function(data){
if(data.msg == "CHECKED!"){
next();
}else{
return res.end(data.msg);
}
});
}
router.get('/activationUser/:activationCode',activationUser,function(req,res){
var data = {
activationCode : req.params.activationCode,
fId : frontalId
}
socketCore.emit('step2', data);
socketCore.on(frontalId + 'step2Resp', function(data){
if(data.msg == 'err'){
return res.end('The Activation Code is INVALID!');
}else{
return res.render('registro2', {title: 'title | '+ data.name + ' ' + data.lastname, user:data});
}
});
});
谢谢!
答案 0 :(得分:0)
当您尝试在已发送完整响应后在res
对象上发送任何内容时,会发生您遇到的特定错误。这通常是由于异步逻辑中的错误而发生的。在您的特定情况下,它可能是因为您每次在路由器被命中时都会使用socketCore.on()
分配新的事件处理程序。这些事件处理程序将累积,并且在第一次触发路径之后,它们将多次执行,触发在同一响应对象上发送多个响应,从而触发该错误。
解决您的特定问题的主要方法是:
使用.once()
代替.on()
,以便事件处理程序在触发后自动删除。
收到回复后手动删除.on()
事件处理程序。
将事件处理程序移到路径之外,以便它只安装一次。
在您的特定情况下,由于socketCore
是所有请求都可用的共享对象,因此您似乎也有竞争条件。如果多个用户在相同的一般时间范围内触发'/activationUser/:activationCode'
路由,那么您将使用socketCore.on()
注册两个事件处理程序(每个被点击的路由一个),您将执行两个socketCore.emit('step2', data);
。但是,你无法将哪个响应与哪个请求相关联,而且这两个响应很容易混淆 - 转向错误的请求。
这突出显示了socket.io连接不是请求/响应的方式。它们是消息/答案,但除非您手动编写特定消息请求与特定答案之间的对应关系,否则无法关联哪个与哪个相关。因此,如果没有分配一些特定的responseID来让您知道哪个响应属于哪个消息,则不能在多用户环境中使用这样的socket.io连接。这只会导致竞争条件。对于这种类型的数据获取,使用HTTP请求/响应实际上更简单,因为每个响应仅与在HTTP体系结构中发出的请求一致。
您可以更改用于发出socketCore请求的体系结构,但是您必须手动为每个请求分配ID,并确保服务器使用属于该请求的响应发回该ID。然后,您可以在接收端编写几行代码,以确保将正确的响应提供给具有匹配请求的代码。