错误:仅在页面刷新时发送标题后才能设置标题

时间:2016-06-25 21:19:58

标签: node.js express socket.io http-headers

我有这个问题只有当我尝试刷新页面而我无法解决时,我尝试了一切但仍然发生了同样的事情。当我在项目中添加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});
        }
    }); 
});

谢谢!

1 个答案:

答案 0 :(得分:0)

当您尝试在已发送完整响应后在res对象上发送任何内容时,会发生您遇到的特定错误。这通常是由于异步逻辑中的错误而发生的。在您的特定情况下,它可能是因为您每次在路由器被命中时都会使用socketCore.on()分配新的事件处理程序。这些事件处理程序将累积,并且在第一次触发路径之后,它们将多次执行,触发在同一响应对象上发送多个响应,从而触发该错误。

解决您的特定问题的主要方法是:

  1. 使用.once()代替.on(),以便事件处理程序在触发后自动删除。

  2. 收到回复后手动删除.on()事件处理程序。

  3. 将事件处理程序移到路径之外,以便它只安装一次。

  4. 在您的特定情况下,由于socketCore是所有请求都可用的共享对象,因此您似乎也有竞争条件。如果多个用户在相同的一般时间范围内触发'/activationUser/:activationCode'路由,那么您将使用socketCore.on()注册两个事件处理程序(每个被点击的路由一个),您将执行两个socketCore.emit('step2', data); 。但是,你无法将哪个响应与哪个请求相关联,而且这两个响应很容易混淆 - 转向错误的请求。

    这突出显示了socket.io连接不是请求/响应的方式。它们是消息/答案,但除非您手动编写特定消息请求与特定答案之间的对应关系,否则无法关联哪个与哪个相关。因此,如果没有分配一些特定的responseID来让您知道哪个响应属于哪个消息,则不能在多用户环境中使用这样的socket.io连接。这只会导致竞争条件。对于这种类型的数据获取,使用HTTP请求/响应实际上更简单,因为每个响应仅与在HTTP体系结构中发出的请求一致。

    您可以更改用于发出socketCore请求的体系结构,但是您必须手动为每个请求分配ID,并确保服务器使用属于该请求的响应发回该ID。然后,您可以在接收端编写几行代码,以确保将正确的响应提供给具有匹配请求的代码。