vue前端SSE工具库|EventSource 替代方案推荐|PUSDN平行宇宙软件开发者网

EventSource 替代方案推荐

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

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

1. fetch-event-source

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

安装方法
复制代码
npm install @microsoft/fetch-event-source
在您的项目中使用
复制代码
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;
  }
}

2. sse.js

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

安装方法
复制代码
npm install sse.js
在您的项目中使用
复制代码
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;
  }
}

3. 使用 Axios 和自定义流处理

如果您的项目已经使用了 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;
  }
}

4. 使用原生 fetch API

如果您想避免引入额外的依赖,可以直接使用现代浏览器支持的 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;
  }
}

总结与建议

  1. 推荐使用 @microsoft/fetch-event-source:这是目前最活跃维护的库,API 设计简洁,功能完善,支持自定义请求头、重试逻辑和错误处理。
  2. 如果项目已经使用了 Axios:可以考虑使用 Axios 配合自定义流处理。
  3. 如果想避免引入额外依赖:可以使用原生 fetch API 实现,但需要自己处理更多的细节。
  4. 所有方案都支持在请求头中传递 Sa-Token,满足您的认证需求。

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

相关推荐
陈震_20 天前
在 Java 中调用 ChatGPT API 并实现流式接收(Server-Sent Events, SSE)
java·开发语言·chatgpt·sse·流式
Once_day23 天前
Linux错误(6)X64向量指令访问地址未对齐引起SIGSEGV
linux·c++·sse·x64·sigsegv·xmm0
前端小菜鸡yy2 个月前
流式输出方案:sse与websocket的使用
网络·websocket·网络协议·sse
Maybe_95272 个月前
python使用httpx_sse调用sse流式接口对响应格式为application/json的错误信息的处理
python·sse·httpx
CAir22 个月前
HTTP SSE 实现
http·libhv·sse
禅思院2 个月前
axios post请求 接收sse[eventsource]数据的
axios·sse·eventsource
zfj3212 个月前
什么事SSE& SSE vs websocket
网络·websocket·网络协议·sse
小马爱打代码2 个月前
Spring Boot 整合 SSE(Server-Sent Events)
spring boot·sse
林犀居士3 个月前
SSE介绍
java·大模型·sse