Node.JS 服务器发送的事件:路由在 res.end() 之后继续到 运行,导致 ERR_STREAM_WRITE_AFTER_END 错误
Node.JS Server Sent Events: Route continues to run after res.end() resulting in ERR_STREAM_WRITE_AFTER_END error
我开始使用服务器发送事件 (SSE),因为我的 Web 应用程序需要从服务器接收实时更新。它不需要向服务器发送任何内容,因此选择了 SSE 而不是 Websockets。
阅读一些示例后,我有以下代码:
On my server, in ./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
On my client, in ./app/index.js I have:
const source = new EventSource('/updates')
source.onmessage = (e) => {
console.log(e)
}
我遇到了 2 个问题:
一旦我从客户端打开一个连接然后关闭
连接(通过关闭选项卡),'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;
仅供参考,如果您已经收到 close
事件,我认为您不需要 res.end()
。如果您单方面尝试关闭与服务器的连接,您将使用 res.send()
,但如果它已经关闭,我认为您不需要它和 none 我见过的代码示例使用就这样。
我想知道您的 res.end()
是否也是您收到两个 close
事件的原因。尝试删除它。
我开始使用服务器发送事件 (SSE),因为我的 Web 应用程序需要从服务器接收实时更新。它不需要向服务器发送任何内容,因此选择了 SSE 而不是 Websockets。
阅读一些示例后,我有以下代码:
On my server, in ./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
On my client, in ./app/index.js I have:
const source = new EventSource('/updates') source.onmessage = (e) => { console.log(e) }
我遇到了 2 个问题:
一旦我从客户端打开一个连接然后关闭 连接(通过关闭选项卡),
'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;
仅供参考,如果您已经收到 close
事件,我认为您不需要 res.end()
。如果您单方面尝试关闭与服务器的连接,您将使用 res.send()
,但如果它已经关闭,我认为您不需要它和 none 我见过的代码示例使用就这样。
我想知道您的 res.end()
是否也是您收到两个 close
事件的原因。尝试删除它。