javascript - 为什么 onmessage 监听器不处理初始 SSE 事件?

标签 javascript node.js express nginx server-sent-events

在此示例中,客户端通过创建新的 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/

相关文章:

javascript - 当我运行 index.html 时 android 没有检测到我的 .css 和 .js 文件怎么办?

javascript - 无法从正则表达式 javascript 获得正确的输出

node.js - 如何获取特定项目在每个文档的数组元素中出现的总次数

javascript - 有没有办法从 Mongoose 模型实例中获取模型名称?

javascript - Node.js 中的异步递归问题

angular - 配置 Angular cli 构建监视模式和 Nodemon 监视的最佳方法是什么?

javascript - React js将分组列数组转换为普通数组

javascript - 如何减少 JavaScript 中的代码重复?

node.js - 重定向时 Express 上未设置 Csrf token

node.js - 如何在 Express 环境中从 images 目录中获取随机图像