将Socket.io与EJS一起使用会导致错误"在发送标题后不能设置标题"

时间:2017-11-02 17:08:37

标签: node.js express socket.io ibm-cloud ejs

我正在尝试在IBM Bluemix上使用Node.js,Express和Socket.io制作应用程序我使用EJS作为视图引擎。这是我的代码的相关部分 -

const express = require('express');
const app = express();
//copied from socket.io tutorial 
const http = require('http').Server(app);
const io = require('socket.io')(http);
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, '../templates'));
...
app.get('/', function (req, res) {
    logger.info('index');
    return res.render('index');
});
...
const port = process.env.PORT || localConfig.port;
http.listen(port);

现在如果我导航到localhost:3000,我收到错误

Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:489:11)
at ServerResponse.setHeader (_http_outgoing.js:496:3)
at ServerResponse.header (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/response.js:767:10)
at ServerResponse.contentType (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/response.js:595:15)
at ServerResponse.send (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/response.js:145:14)
at done (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/response.js:1004:10)
at tryHandleCache (/home/aniket/Documents/HumbleHelper/node_modules/ejs/lib/ejs.js:228:10)
at View.exports.renderFile [as engine] (/home/aniket/Documents/HumbleHelper/node_modules/ejs/lib/ejs.js:437:10)
at View.render (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/view.js:135:8)
at tryRender (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/application.js:640:10)

从日志中我可以看到' index'已被调用两次,然后是错误。但是,如果我删除这一行 -

const io = require('socket.io')(http);

工作正常。我已经阅读了其他一些问题,提到不止一次调用res。***函数可能会导致此问题。我的猜测是在服务器上构造socket.io会导致一些问题。

版本:

socket.io:2.0.4

表示:4.6.2

ejs 2.5.7

节点:6.9.0

修改

在评论/取消注释所有模块后,我在应用程序顶部找到了原因

require('appmetrics-dash').attach();
require('appmetrics-prometheus').attach();

1 个答案:

答案 0 :(得分:0)

最有可能的是,您正在构建socket.io侦听器来处理res。因此,当Socket.io收到另一个广播时,它会使用之前已发送的res。

要解决此问题,请在完成此操作后删除侦听器,以便可以使用新的res构建新的侦听器。对于实例:

socket.on('example', function(data){
     socket.removeAllListeners('example');
     res.send(data);
});
编辑:哎呀!不知怎的,我读错了大声笑的问题。试试这个:

var express = require('express');
var app = express();
var http = require('http').createServer(app);
var io = require('socket.io').listen(http);