当前位置: 首页 > news >正文

【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) 工具函数(统一格式化输出)。
http://www.dtcms.com/a/389661.html

相关文章:

  • JAVA算法练习题day15
  • 线性表---双链表概述及应用
  • 作业帮前端面试(准备)
  • 51单片机-使用单总线通信协议驱动DS18B20模块教程
  • 全文单侧引号的替换方式
  • NVIDIA RTX4090 在Ubuntu系统中开启P2P peer access 直连访问
  • 再次深入学习深度学习|花书笔记2
  • 中移物联ML307C模组OPENCPU笔记1
  • 计算机视觉
  • VScode实现uniapp小程序开发(含小程序运行、热重载等)
  • Redis的各种key问题
  • 元宇宙与医疗产业:数字孪生赋能医疗全链路革新
  • 为你的数据选择合适的分布:8个实用的概率分布应用场景和选择指南
  • 掌握Stable Diffusion WebUI:模型选择、扩展管理与部署优化
  • LVGL拼音输入法优化(无bug)
  • 多层感知机:从感知机到深度学习的关键一步
  • PostgreSQL绿色版整合PostGIS插件,以Windows 64位系统为例
  • GEO优化推荐案例:2025年上海源易信息科技的全链路实践
  • 时空预测论文分享:多模态融合 空间索引结构 超图 时演化因果关系
  • 智能手机产量增长4%
  • MySQL高可用MHA实战指南
  • Coze源码分析-资源库-创建工作流-后端源码-核心技术/总结
  • 《棒球团建》国家级运动健将·棒球1号位
  • 基于STM32单片机生理监控心率脉搏TFT彩屏波形曲线加体温测量
  • Selenium 浏览器自动化完全指南:从环境搭建到实战应用
  • C51单片机——开发学习:中断
  • 树与二叉树【数据结构】
  • RPM包版本号系统解析:设计哲学、比较规则与实践指南
  • IDEA启动异常
  • vite使用vue2项目