在此示例中,客户端通过创建新的 EventSource 连接到 Node Express 服务器。服务器在初始连接时发送 SSE 事件,然后每隔 30 秒发送一次。问题是客户端的 onmessage 处理程序不是由连接时发送的初始 SSE 事件触发的,而是由所有后续事件触发的。如果我在建立连接后立即停止服务器,这实际上会在客户端触发一个事件,该事件表明数据实际上是在没有被处理的情况下收到的(或者初始 res.write 仅由服务器触发)关机):
服务器:
let data = {mydata: 123};
function eventsHandler(req, res, next) {
const headers = {
"Content-Type": "text/event-stream",
Connection: "keep-alive",
"Cache-Control": "no-cache",
};
res.writeHead(200, headers);
// After client opens connection we send data string, but client doesn't handle this correctly
// Event is only triggered on client if I stop the server after sending this message
res.write(`data: ${JSON.stringify(data)}\n\n`);
console.log("sent SSE");
const clientId = Date.now();
console.log(clientId, " connected");
const newClient = {
id: clientId,
res,
};
clients.push(newClient);
req.on("close", () => {
console.log(`${clientId} Connection closed`);
clients = clients.filter((c) => c.id !== clientId);
});
}
// these events are received and handled correctly on client
function sendEventsToAll(datadict) {
clients.forEach((c) => c.res.write(`data: ${JSON.stringify(datadict)}\n\n`));
}
// Route to open SSE connection
app.get("/events", eventsHandler);
// Loop to send SSE every 30 seconds - these are all received and handled correctly
async function wait() {
sendEventsToAll(data);
setTimeout(wait, 30000);
}
wait();
浏览器:
const events = new EventSource(url)
// This handles every SSE event except the one that is written immediately upon connection
// If I stop the server after connection, this will trigger and reveal the data was received but not handled
events.onmessage = event => {
const newData = JSON.parse(event.data)
console.log("newData", newData)
}
编辑:我还应该补充一点,我正在使用 nginx 作为反向代理 - 这是否可以缓冲第一个 res.write 而不是出于某种原因立即发送它?
最佳答案
这是由 nginx 中的 proxy_buffering 引起的,默认情况下是“打开”的。
在 nginx 配置中关闭它解决了这个问题:
server {
# server config here...
location / {
# proxy config here...
proxy_buffering off; # resolves issue
}
}
关于javascript - 为什么 onmessage 监听器不处理初始 SSE 事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62660879/