25-10-29-SSE学习笔记


本文为SSE视频的学习笔记

笔记

  1. 实现原理:
    前端 ContextType 设置为”text/event-stram;chatset=utf-8”
    后端:每次往响应写入数据就会往前端发一个消息,调用 end 结束响应就会断开(但是这样断开,前端会主动重连)

  2. 一个坑:SSE 的网络协议要求,write 的格式得是data: ${arr[counter]}\n\n,否则会出现前端 onMessage 无法接受到相应相应的问题。
    服务器一定不能主动断开,这样会导致前端无法重连,除非前端关闭再连,否则无法主动发消息。前端也是一样,一旦 close,除非重新创建实例,否则无法用同一个实例重连。(服务器通过 end 的响应断开,前端还是会重连;服务器要通过状态码断开)

  3. 默认使用 EventSource 来获取 readableStream 对象,但这个方法不支持 token(虽然可以放进 query 里,但就将 token 暴露给了用户);
    可以使用 EventSourcePolyfill(url)调库来支持 cookie 的 token,或者手写自定义 SSE 类。

后端代码

const express = require("express");
const cors = require("cors");
const app = express();

app.use(cors());
app.get("/api/sse", (req, res) => {
res.writeHead(200, {
"Content-Type": "text/event-stream;charset=utf-8", //声明这是事件流
Connection: "keep-alive", // 一般默认是keep-alive
});

console.log("链接上了");

let counter = 0;
const intervalId = setInterval(() => {
const arr = ["1", "2", "3", "4", "5", "6"];
res.write(`data: ${arr[counter]}\n\n`);
counter++;
if (counter >= arr.length) {
clearInterval(intervalId);
}
}, 1000);
req.on("close", () => {
console.log("客户端断开连接");
clearInterval(intervalId);
res.end();
});
});

app.listen(3000, () => console.log("服务器运行在端口 3000"));

前端

import { ref } from "vue";
const message = ref("");

const eventSource = new EventSource("http://localhost:3000/api/sse");
eventSource.onmessage = (valueText) => {
console.log(valueText);
message.value = message.value + valueText.data;
};
eventSource.addEventListener("newMessage", (event) => {
console.log("触发了事件后:", event);
});

文章作者: Qijia Huang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Qijia Huang !
  目录