由于我的Web应用程序需要从服务器接收实时更新,因此我开始使用服务器发送事件(SSE)。它不需要发送任何内容到服务器,因此通过Websockets选择了SSE。
在阅读了一些示例之后,我有以下代码:
在我的服务器上,在./ src / routers / mainRouter.js中,我有:
router.get('/updates', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }) // Listens for 'event' and sends an 'Event triggered!' message to client when its heard. eventEmitter.addListener('event', () => { console.log('Event triggered! Sending response.') res.write('data: Event triggered!\n\n') }) req.on('close', () => { console.log('Connection to client closed.') res.end() }) }) module.exports = router
在我的客户端上,在[[./app/index.js中,我有:
const source = new EventSource('/updates') source.onmessage = (e) => { console.log(e) }
我有两个问题:
- 一旦从客户端打开连接,然后关闭连接(通过关闭选项卡),
'close'
事件触发两次导致req.on('close')
中的代码块运行两次。我不确定为什么会这样。我在服务器端的console
看起来如下:
Event triggered! Sending response. Connection to client closed. Connection to client closed.
req.end()
,但路由器仍然继续监听该频道上的事件并尝试发送沿着该渠道做出回应,导致ERR_STREAM_WRITE_AFTER_END
错误和服务器崩溃。所以最终控制台输出看起来像:Event triggered! Sending response. // First event triggers.
Connection to client closed. // 'close' event fires.
Connection to client closed. // 'close' event fires a second time (not sure why).
Event triggered! Sending response. // Router continues listening for 'event' and sends another response although res.end() was called earlier
events.js:187
throw er; // Unhandled 'error' event
^
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
router.get('/updates', (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
function listener(event) {
console.log('Event triggered! Sending response.');
res.write('data: Event triggered!\n\n');
}
// Listens for 'event' and sends an 'Event triggered!' message to client when its heard.
eventEmitter.addListener('event', listener);
req.on('close', () => {
// remove listener so it won't try to write to this stream any more
eventEmitter.removeListener('event', listener);
console.log('Connection to client closed.');
res.end();
});
});
module.exports = router;