我正在开始使用服务器发送事件 (SSE),因为我的 Web 应用程序需要从服务器接收实时更新。它不需要向服务器发送任何内容,因此选择 SSE 而不是 Websockets。
阅读了一些示例后,我有以下代码:
在我的服务器上,在./src/routers/mainRouter.js I have:
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 I have:
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;
仅供参考,我认为你不需要res.end()
当您已经收到close
事件。你会使用res.send()
如果您单方面尝试关闭与服务器的连接,但如果它已经关闭,我认为您不需要它,并且我见过的代码示例都没有以这种方式使用它。
我想知道你是否有可能res.end()
这也是你得到两个的原因close
事件。尝试将其删除。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)