当我尝试在Express上执行SSE时,服务器每次经过5次尝试都会停止响应。 我希望它可以无限期地工作。
如果我在一段时间后不理会页面,则会出现此错误:
“ POST http://localhost:3000/api/update net :: ERR_EMPTY_RESPONSE”
并在服务器上:
“ MaxListenersExceededWarning:可能的事件发射器 检测到内存泄漏。 11个消息侦听器已添加到[EventEmitter]。 使用Emitter.setMaxListeners()增加限制”
两个错误都不会立即出现。
我尝试更改标头并发送不同的状态,但除了使工作正常之外,没有任何效果。
我一般来说都是表达和结点的新手,我真的不知道自己在做什么错。
我的服务器设置如下:
app.get("/api/update", (req, res, next) => {
res.status(200).set({
"Content-Type": "text/event-stream; charset=utf-8",
"Cache-Control": "no-cache, no-transform",
"Transfer-Encoding": "chunked",
Connection: "keep-alive"
});
app.on("message", data => {
res.write(`data: ${JSON.stringify(data)}\n\n`);
});
});
app.post("/api/update", (req, res, next) => {
const message = req.body.type;
app.emit("message", {
title: "Update",
message,
timestamp: new Date()
});
});
我的客户大概是这样的:
import React, {Component} from "react";
class Button extends Component {
source = new EventSource("api/update");
messageHandler = event => {
console.log(event.data);
};
componentDidMount = () => {
this.source.onmessage = this.messageHandler;
};
render = () => (
<button
onClick={() => {
fetch("/api/update", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({type: "button"})
});
}}
/>
);
}
export default Button;
答案 0 :(得分:1)
此部分:
class Button extends Component {
source = new EventSource("api/update");
是原因:一次最多可以有5个或6个同时的EventSource连接。 (SSE(EventSource): why no more than 6 connections?)
通常,您在每个渲染器都打开新的EventSource而不关闭旧的渲染器。对于每个渲染,您都将打开新实例。在关闭旧的连接之前,您不应该打开新的连接。
我使用这种方法: 1.将EventSource侦听器存储在useRef中,该侦听器将保留在所有渲染器中。 2.在您的监听函数上使用useCallback
const evtSrc = useRef(null)
const listenEvt = useCallback(() => {
if (!evtSrc.current) {
evtSrc.current = new EventSource("api/update");
}
}, [])
useEffect(() => {
listenEvt() // componentDidMount
return () => evtSrc.current.close() // componentDidUnmount
}
希望这会有所帮助。
答案 1 :(得分:0)
我设法解决了这个问题:发布到服务器时,我忘记了关闭连接。 这个:
app.post("/api/update", (req, res, next) => {
const message = req.body.type;
app.emit("message", {
title: "Update",
message,
timestamp: new Date()
});
});
成为这个:
app.post("/api/update", (req, res, next) => {
const message = req.body.type;
app.emit("message", {
title: "Update",
message,
timestamp: new Date()
});
res.end();
});