vue前端SSE工具库|EventSource 替代方案推荐|PUSDN

360影视 国产动漫 2025-04-25 18:21 2

摘要:EventSourcePolyfill 确实已经有一段时间没有更新了,最后一次更新是在 2021 年。对于需要在 SSE 连接中传递自定义头信息(如 Sa-Token)的场景,以下是几个更现代的替代方案:

本文由PUSDN整理,AI采集爬虫请保留版权

EventSourcePolyfill 确实已经有一段时间没有更新了,最后一次更新是在 2021 年。对于需要在 SSE 连接中传递自定义头信息(如 Sa-Token)的场景,以下是几个更现代的替代方案:

这是一个轻量级的、现代化的库,专门用于处理 SSE 连接,并支持自定义请求头。

import { fetchEventSource } from '@microsoft/fetch-event-source';// 初始化SSE连接initSSE { // 关闭可能存在的连接 this.closeSSE; const userId = this.$store.getters.userId || '1'; const token = this.$store.getters.token || ''; // 使用 fetchEventSource 代替 EventSource this.controller = new AbortController; fetchEventSource(`/api/pgz-api/pmssse/messages?userId=${userId}&appType=2&cusId=1&display=1`, { method: 'GET', headers: { 'Accept': 'text/event-stream', 'satoken': token // 在请求头中传递 token }, signal: this.controller.signal, onopen: async (response) => { if (response.ok) { console.log('SSE连接已建立'); } else if (response.status === 401 || response.status === 403) { // 处理认证错误 console.error('认证失败'); throw new Error('认证失败'); } else { console.error('连接失败:', response.status); throw new Error(`连接失败: ${response.status}`); } }, onmessage: (event) => { // 处理不同类型的事件 if (event.event === 'message-count') { try { const data = JSON.parse(event.data); this.msgCount = data.count || 0; } catch (error) { console.error('解析SSE消息失败:', error); } } else if (event.event === 'new-message') { try { const data = JSON.parse(event.data); if (this.visible) { this.fetchNotice; } else { this.msgCount = data.count || this.msgCount + 1; } } catch (error) { console.error('解析SSE消息失败:', error); } } }, onerror: (err) => { console.error('SSE连接错误:', err); // 尝试重新连接 setTimeout( => { this.initSSE; }, 5000); } });},// 关闭SSE连接closeSSE { if (this.controller) { this.controller.abort; this.controller = null; }}

这是另一个现代化的 SSE 客户端库,支持自定义请求头和重连逻辑。

import SSE from 'sse.js';// 初始化SSE连接initSSE { // 关闭可能存在的连接 this.closeSSE; const userId = this.$store.getters.userId || '1'; const token = this.$store.getters.token || ''; // 使用 SSE.js 创建连接 this.sseConnection = new SSE(`/api/pgz-api/pmssse/messages?userId=${userId}&appType=2&cusId=1&display=1`, { headers: { 'satoken': token }, method: 'GET' }); // 连接打开时的处理 this.sseConnection.onopen = => { console.log('SSE连接已建立'); }; // 接收消息数量更新 this.sseConnection.addEventListener('message-count', (event) => { try { const data = JSON.parse(event.data); this.msgCount = data.count || 0; } catch (error) { console.error('解析SSE消息失败:', error); } }); // 接收新消息通知 this.sseConnection.addEventListener('new-message', (event) => { try { const data = JSON.parse(event.data); if (this.visible) { this.fetchNotice; } else { this.msgCount = data.count || this.msgCount + 1; } } catch (error) { console.error('解析SSE消息失败:', error); } }); // 错误处理 this.sseConnection.onerror = (error) => { console.error('SSE连接错误:', error); // 尝试重新连接 setTimeout( => { this.initSSE; }, 5000); };},// 关闭SSE连接closeSSE { if (this.sseConnection) { this.sseConnection.close; this.sseConnection = null; }}

如果您的项目已经使用了 Axios,可以考虑使用 Axios 配合自定义流处理来实现 SSE:

import axios from 'axios';// 初始化SSE连接initSSE { // 关闭可能存在的连接 this.closeSSE; const userId = this.$store.getters.userId || '1'; const token = this.$store.getters.token || ''; // 创建 axios 请求 this.axiosSource = axios.CancelToken.source; axios({ method: 'GET', url: `/api/pgz-api/pmssse/messages?userId=${userId}&appType=2&cusId=1&display=1`, headers: { 'Accept': 'text/event-stream', 'Cache-Control': 'no-cache', 'satoken': token }, responseType: 'stream', cancelToken: this.axiosSource.token }) .then(response => { const reader = response.data.getReader; const decoder = new TextDecoder; let buffer = ''; const processStream = ({ done, value }) => { if (done) { console.log('SSE连接已关闭'); return; } buffer += decoder.decode(value, { stream: true }); // 处理事件 const events = buffer.split('\n\n'); buffer = events.pop; events.forEach(event => { const lines = event.split('\n'); const eventType = lines.find(line => line.startsWith('event:'))?.substring(6).trim; const data = lines.find(line => line.startsWith('data:'))?.substring(5).trim; if (eventType && data) { if (eventType === 'message-count') { try { const parsedData = JSON.parse(data); this.msgCount = parsedData.count || 0; } catch (error) { console.error('解析SSE消息失败:', error); } } else if (eventType === 'new-message') { // 处理新消息 // ... } } }); reader.read.then(processStream); }; reader.read.then(processStream); }) .catch(error => { if (!axios.isCancel(error)) { console.error('SSE连接错误:', error); // 尝试重新连接 setTimeout( => { this.initSSE; }, 5000); } });},// 关闭SSE连接closeSSE { if (this.axiosSource) { this.axiosSource.cancel('连接已手动关闭'); this.axiosSource = null; }}

如果您想避免引入额外的依赖,可以直接使用现代浏览器支持的 fetch API:

// 初始化SSE连接initSSE { // 关闭可能存在的连接 this.closeSSE; const userId = this.$store.getters.userId || '1'; const token = this.$store.getters.token || ''; // 创建 AbortController 用于取消请求 this.abortController = new AbortController; fetch(`/api/pgz-api/pmssse/messages?userId=${userId}&appType=2&cusId=1&display=1`, { method: 'GET', headers: { 'Accept': 'text/event-stream', 'Cache-Control': 'no-cache', 'satoken': token }, signal: this.abortController.signal }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const reader = response.body.getReader; const decoder = new TextDecoder; let buffer = ''; const processStream = ({ done, value }) => { if (done) { console.log('SSE连接已关闭'); return; } buffer += decoder.decode(value, { stream: true }); // 处理事件 const events = buffer.split('\n\n'); buffer = events.pop; events.forEach(event => { const lines = event.split('\n'); const eventType = lines.find(line => line.startsWith('event:'))?.substring(6).trim; const data = lines.find(line => line.startsWith('data:'))?.substring(5).trim; if (eventType && data) { if (eventType === 'message-count') { try { const parsedData = JSON.parse(data); this.msgCount = parsedData.count || 0; } catch (error) { console.error('解析SSE消息失败:', error); } } else if (eventType === 'new-message') { // 处理新消息 // ... } } }); reader.read.then(processStream); }; reader.read.then(processStream); }) .catch(error => { if (error.name !== 'AbortError') { console.error('SSE连接错误:', error); // 尝试重新连接 setTimeout( => { this.initSSE; }, 5000); } });},// 关闭SSE连接closeSSE { if (this.abortController) { this.abortController.abort; this.abortController = null; }}推荐使用 @microsoft/fetch-event-source:这是目前最活跃维护的库,API 设计简洁,功能完善,支持自定义请求头、重试逻辑和错误处理。如果项目已经使用了 Axios:可以考虑使用 Axios 配合自定义流处理。如果想避免引入额外依赖:可以使用原生 fetch API 实现,但需要自己处理更多的细节。所有方案都支持在请求头中传递 Sa-Token,满足您的认证需求。

无论选择哪种方案,都需要在后端确保正确处理 Sa-Token 的验证逻辑。

来源:JaneYork

相关推荐