将 Socket.io 与 EJS 一起使用会导致错误"Can't set headers after they're sent"



我正在尝试在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);

现在,如果我导航到本地主机: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();

最有可能的是,您正在构造 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);

相关内容

最新更新