【JavaScript】SSE
1. SSE 是以什么格式的数据发送的?
SSE(Server-Sent Events)的数据格式是 text/event-stream
,即基于 UTF-8 编码的文本流。
它有固定的格式规则:
-
每个事件由若干行组成,以
\n\n
(空行) 作为分隔符。 -
常用字段:
data:
消息内容(可以多行,客户端会拼接成一个字符串)event:
自定义事件名(默认是message
)id:
消息 ID(客户端断线重连时可以用Last-Event-ID
继续)retry:
建议客户端重连间隔(单位:毫秒)
示例:
id: 1
event: message
data: 这是第一条消息event: news
data: {"title":"新闻","content":"今天有新内容"}
2. 如何支持其他格式(比如 JSON、body 数据)?
SSE 传输的本质是 文本,所以:
- 如果要传 JSON → 用
JSON.stringify
转成字符串再放到data:
- 如果要传二进制(比如图片、文件) → 转成 Base64 或 Blob 的字符串,再传
- 如果要传自定义格式 → 依然先序列化成文本
前端接收时再做反序列化:
evtSource.onmessage = (event) => {try {const data = JSON.parse(event.data);console.log("收到 JSON:", data);} catch {console.log("收到文本:", event.data);}
};
👉 总结:SSE 不支持真正的 body
传输,它就是基于 HTTP 响应流。要支持其他格式,必须 自己封装成文本再传。
3. 如何封装 SSE?
为了更方便使用,一般会对 SSE 封装一个工具类:
前端封装
class SSEClient {constructor(url) {this.source = new EventSource(url);}on(event, callback) {this.source.addEventListener(event, (e) => {try {callback(JSON.parse(e.data));} catch {callback(e.data);}});}close() {this.source.close();}
}// 使用
const sse = new SSEClient("/sse");
sse.on("message", (data) => console.log("默认消息:", data));
sse.on("news", (data) => console.log("新闻:", data));
后端封装(Node.js)
function sseHandler(req, res) {res.setHeader("Content-Type", "text/event-stream");res.setHeader("Cache-Control", "no-cache");res.setHeader("Connection", "keep-alive");function send(event, data, id) {if (id) res.write(`id: ${id}\n`);if (event) res.write(`event: ${event}\n`);res.write(`data: ${typeof data === "string" ? data : JSON.stringify(data)}\n\n`);}// 测试推送send("message", "连接成功", 1);setInterval(() => send("news", { title: "最新消息", ts: Date.now() }), 3000);req.on("close", () => console.log("客户端断开连接"));
}
🎯 总结
- SSE 以
text/event-stream
文本流格式发送数据,每个事件由data: ...
构成,以空行分隔。 - 不支持直接发送 JSON、二进制,要先序列化成字符串。JSON 用
JSON.stringify
,二进制用 Base64。 - 封装思路:前端封装一个
SSEClient
(自动 JSON 解析、事件监听),后端封装一个send(event, data, id)
工具函数(统一格式化输出)。