为什么 onmessage 侦听器不处理初始 SSE 事件?
Why is the initial SSE event not handled by the onmessage listener?
在此示例中,客户端通过创建新的 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
}
}
在此示例中,客户端通过创建新的 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
}
}