写在前面:
兄弟们,我手里有个长期项目,考虑接私活的可以看看我GitHub!
https://github.com/ccy-233/coder2retire
SSE(Server-Sent Events)是一种基于 HTTP 协议,用于实现服务器主动向客户端推送数据的技术。它在客户端与[服务器]之间建立一条持久化连接,并通过这条连接实现服务器向客户端的实时数据推送,而客户端不能发送数据给服务端。
总之——SSE是一种允许服务器向客户端单向发送数据的技术。
[EventSource](https://developer.mozilla.org/zh-CN/docs/Web/API/EventSource "EventSource")
**
EventSource
**接口是Web内容与服务器发送事件通信的接口。一个
EventSource
实例向HTTP服务器开启一个持久化的连接,以text/event-stream
格式发送事件,此连接会一直保持开启直到通过调用EventSource.close()关闭。
示例:在一个vue的页面中
const initSSE = () => { eventSource = new EventSource('http://地址'); eventSource.onmessage = (event) => { console.log("收到消息内容是:", event.data) }; eventSource.onerror = (error) => { console.error("SSE 连接出错:", error); eventSource.close(); };} onMounted(() => { initSSE();}); onUnmounted(() => { if (eventSource) { eventSource.close(); }});
EventSource
**的事件open
在与事件源的连接打开时触发
message
在从事件源接收到数据时触发
error
在事件源连接未能打开时触发
具名事件
当从服务器端接收到指定了event字段的事件时触发,这将创建一个以该键值为值的特定事件
如果想要在建立SSE连接的时候携带token,需要用到 event-source-polyfill
EventSourcePolyfill 是 EventSource 封装好了的一个方法,可以直接配置请求头
首先安装依赖
npm install event-source-polyfill --save
项目中使用,完整的封装代码如下 sse.js 文件
import {getToken} from "@/utils/auth";import {EventSourcePolyfill} from "event-source-polyfill"; let eventSource = null;let reconnectAttempts = 0; // 重连次数 export default function subscribeWarnMsg(proxy, url) { if (eventSource) { console.log("sse已经存在:", eventSource); return eventSource; } else { eventSource = new EventSourcePolyfill(import.meta.env.VITE_APP_BASE_API + url, { heartbeatTimeout: 3 * 60 * 1000, headers: { Authorization: 'Bearer ' + getToken(), Accept: 'text/event-stream' }, withCredentials: true, }) eventSource.onopen = function (e) { console.log(e, "连接刚打开时触发"); reconnectAttempts = 0; // 重置重连次数 }; eventSource.onmessage = (event) => { console.log("收到消息内容是:", event.data) }; eventSource.onerror = (event) => { console.error("SSE 连接出错:", event); eventSource.close(); // 关闭连接 eventSource = null; // 自动重连逻辑 reconnectAttempts++; const reconnectDelay = Math.min(30000, 1000 * Math.pow(2, reconnectAttempts)); // 计算重连延迟,最大延迟为30秒 console.log(`将在 ${reconnectDelay} 毫秒后尝试重连...`); // 等待一定时间后重连 setTimeout(() => { if (!eventSource) { console.log("尝试重连 SSE..."); subscribeWarnMsg(proxy, url); // 递归调用重连 } }, reconnectDelay); } return eventSource; }}
页面中使用 test.vue 文件
import subscribeWarnMsg from '@/../sse'const {proxy} = getCurrentInstance(); const sse = ref() function initSSE() { sse.value = subscribeWarnMsg(proxy, `/system/sse/connect`); sse.value.onmessage = async (event) => { info.value = await JSON.parse(event.data) }} onMounted(() => { initSSE();}); onUnmounted(() => { sse.value.close()});