欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > SSE技术的基本理解以及在项目中的使用

SSE技术的基本理解以及在项目中的使用

2025/5/5 22:56:34 来源:https://blog.csdn.net/qq_74114417/article/details/147693869  浏览:    关键词:SSE技术的基本理解以及在项目中的使用

文章目录

  • 一、什么是 SSE?
    • 1. 基本概念
    • 2. 核心特点
    • 3. 工作原理
    • 4. SSE 与 HTTP 的关系
    • 5. 与 WebSocket 的比较
  • 二、客户端 API -- EventSource
    • 1. EventSource
    • 2. 基本用法
  • 三、我在 Vue3 项目中的使用
    • 1. ​​EventSourcePolyfill 与 EventSource 的关系 ​
    • 2. 如何使用 EventSourcePolyfill?​
    • 3. 在项目中使用

最近在写项目时,了解了 SSE 的技术,通过这篇文章,简单的记录一下自己在项目中学习 SSE 的收获。

一、什么是 SSE?

1. 基本概念

Server-Sent Events (SSE) 是一种基于 HTTP 的服务器到客户端的 ​​ 单向实时通信技术 ​​,允许服务器主动向客户端单向推送数据的技术。

2. 核心特点

  • 单向通信:仅支持服务器到客户端的单项数据推送、
  • 基于 HTTP:使用简单,无需额外协议,兼容现有 HTTP 基础设施。
  • 长连接:通过长轮询(long-polling)机制保持连接,减少频繁建立连接的开销。
  • 自动重连:连接中断时,客户端会自动尝试重新连接。
  • 轻量协议:数据格式简单(纯文本),适合高频底数据量的场景。

3. 工作原理

示例图
在这里插入图片描述

文字描述:

  1. 客户端发起连接
// url为服务器接口地址
const eventSource = new EventSource('url')// 浏览器向服务器发送一个 HTTP GET 请求,等待服务器响应。
  1. 服务器建立长连接

服务器响应头需包含:

HTTP/1.1 200 OK
Content-Type: text/event-stream
Connection: keep-alive
Cache-Control: no-Cache# 服务器保持连接开放,准备推送数据
  1. 服务器推送数据

数据格式规则:

  • 每条消息以 data: 开头, 一两个换行符 \n\n 结尾。
  • 可定义自定义事件(如: event: update
data: Hello!\n\n
event: price\n
data: {"symbol": "BTC", "price": 42000}\n\n
  1. 客户端接收并处理数据

监听默认的 message 事件或自定义事件(如 price)

eventSource.onmessage = (e) => {/** 处理默认事件 */
}
eventSource.addEventListener('price', (e) => {/** 处理自定义事件 */
})
  1. 连接终止与重连

客户端或服务器可主动关闭连接:

eventSource.close() // 客户端主动关闭

若连接意外中断(如网络问题),客户端自动重连。

4. SSE 与 HTTP 的关系

  • 基于 HTTP/1.1 及以上 ​​:SSE 使用 HTTP 协议,兼容性良好。
  • ​ 轻量级协议 ​​:无需复杂握手(如 WebSocket),适合简单实时场景。
  • 数据分块传输 ​​:服务器通过 HTTP 分块编码(Chunked Encoding)持续发送数据。

5. 与 WebSocket 的比较

特性SSEWebSocket轮询(Polling)
通信方向单向(服务器->客户端)双向单向(客户端主动)
协议HTTPWebSocket(WS)HTTP
连接开销低(长连接)中(双向握手)高(频繁连接)
适用场景实时通知、数据监控聊天、游戏、协作低频更新

二、客户端 API – EventSource

1. EventSource

在 MDN 中介绍到:EventSource 接口是 web 内容与服务器发送事件通信的接口。一个 EventSource 实例会对 HTTP 服务器开启一个持久化的连接,以 text/event-stream 格式发送事件,此连接会一直保持开启直到通过调用 EventSource.close() 关闭。

可以通过下方代码检测某种浏览器是否有这个对象

if (`EventSource` in window) {// ...
}

使用 SSE 时,浏览器先创建一个 EventSource 实例,向服务器发起连接。

const eventSource = new EventSource(url)

url 是服务器的接口地址,例如:https://example.com/message/sse,如果需要跨域,可以指定第二个参数,打开 withCredentials 属性,表示是否一起发送 Cookie

const eventSource = new EventSource(url, { withCredentials: true })

EventSource 实例的 readyState 属性,表明连接的当前状态。该属性只读,可以取以下值。

  • 0:相当于 常量 EventSource.CONNECTING, 表示 连接还未建立,或者断线正在重连。
  • 1:相当于常量 EventSource.OPEN,表示连接已经建立,可以接受数据。
  • 2:相当于常量 EventSource.CLOSED,表示连接已断,且不会重连。

2. 基本用法

  1. 连接一旦建立,就会触发 open 事件,可以在 onopen 属性定义回调函数。
// 建立连接
const eventSource = new EventSource(url, { withCredentials: true })eventSource.onopen = (e) => {// ...
}
  1. 客户端收到服务器发来的数据,就会触发 message 事件,可以在 onmessage 属性的回调函数。
eventSource.onmessage = (e) => {// e.data 就是服务器端传回的数据(文本格式)。const data = e.data// handle message
}
  1. 如果发生通信错误(比如连接中断),就会触发 error 事件,可以在 onerror 属性定义回调函数。
eventSource.onerror = (e) => {// handle error
}
  1. close 方法用于关闭 SSE 连接
eventSource.close()
  1. 自定义事件

默认情况下,服务器发来的数据,总是触发浏览器 EventSource 实例的 message 事件。开发者还可以自定义 SSE 事件,这种情况下,发送回来的数据不会触发 message 事件。

eventCource.addEventListener('price', (e) => {const data = event.data// handle message
})

上面的代码中,浏览器对 SSE 的 price 事件进行监听。注意:事件要前后端进行约定

三、我在 Vue3 项目中的使用

我在做 SSE 模块时,通过创建了一个 messageStore 仓库进行 SSE 相关内容的初始化和消息的处理。除此之外,原生的 EventSource 是无法满足项目中的需求的,因为原生的 EventSource 无法进行自定义请求头等,所以采用了一个第三方库: EventSourcePolyfill。它实现了与原生 EventSource 相同的 API,但扩展了原生 EventSource 的功能(如跨域请求、自定义请求头等),并解决了原生 EventSource 在 ​​IE、旧版浏览器 ​​ 中的兼容性问题。

1. ​​EventSourcePolyfill 与 EventSource 的关系 ​

特性EventSource​EventSourcePolyfill
定位 ​​浏览器原生对象第三方 Polyfill 库
​ 兼容性 ​​仅支持现代浏览器(Chrome、Firefox、Safari 等)支持旧浏览器(如 IE 10+、旧版 Android/iOS)
​ 功能扩展 ​​仅基础功能支持自定义请求头、跨域凭据、重试策略等
​ 依赖关系 ​​无需额外引入需通过 npm 或 CDN 引入库
​API 一致性 ​​完全一致完全兼容原生 API,无学习成本

2. 如何使用 EventSourcePolyfill?​

  1. 安装库
npm install event-source-Polyfill
  1. 引入并创建实例(基本与原生的 EventSource 一致)
import { EventSourcePolyfill } from 'event-source-polyfill'// 创建 SSE 连接(支持自定义请求头和跨域凭据)
const eventSource = new EventSourcePolyfill('/sse-endpoint', {headers: {Authorization: 'Bearer xxxx' // 自定义请求头},withCredentials: true, // 跨域时携带 CookieheartbeatTimeout: 30000 // 超时时间(毫秒)
})// 监听消息(与原生 EventSource 完全一致)
eventSource.onmessage = (event) => {console.log('收到数据:', event.data)
}

3. 在项目中使用

import { defineStore } from 'pinia'
import { useUserStore } from '@/store/userStore'
import { EventSourcePolyfill } from 'event-source-polyfill'export const useMessageStore = defineStore('message', {state: () => ({// 存储原始消息列表messages: [],// EventSourcePolyfill实例eventSource: null// ....处理消息的变量}),action: {// 初始化连接initSSE() {// 1. 关闭旧连接(防止重复连接)if (this.eventSource) {this.eventSource.close()}// 2. 需要进行token校验的话可以获取tokenconst userStore = useUserStore()const token = userStore.getToken()// 3. 创建实例this.eventSource = new EventSourcePolyfill(URL, {headers: {Authorization: `Bearer ${token}`,Accept: 'text/event-stream'},withCredentials: true // 携带 cookiesheartbeatTimeout: 60000 // 心跳检测})// 记录重连次数let reconnectAttempts = 0const MAX_RETRIES = 5 // 最大重试次数// 连接成功回调this.eventSource.onopen = (e) => {console.log('SSE 连接成功')// reconnectAttempts = 0; // 重置重试计数器};// 消息处理this.eventSource.onmessage = (event) => {try {this.handleMessage(event)} catch (error) {console.error('消息处理失败:', error)}};// 错误处理(核心修改)this.eventSource.onerror = (error) => {console.error('SSE 连接异常:', error)// 仅在连接完全关闭时重连if (this.eventSource?.readyState === EventSource.CLOSED) {console.log('连接已关闭,尝试重连...')this.handleSSEError(reconnectAttempts, MAX_RETRIES)reconnectAttempts++}};},closeSSE () {if (this.eventSource) {this.eventSource.close();this.eventSource = null;}if (this.reconnectTimer) {clearTimeout(this.reconnectTimer);}},handleMessage () {//....}}
})

以上是我对 SSE 的理解,本人还在学习阶段,能力有限,有什么不对的地方还请指出来。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词