如何使用fetch+SSE和EventSource来处理text/event-stream数据

优缺点:

eventSource


        eventSource: null, // 存储 EventSource 实例
        this.eventSource.close() // 关闭/暂停

        this.eventSource = new EventSource(`https://XXXXXXXXXXX`, {
          headers: {
            'Authorization': `Bearer #####`//自定义请求头
          }
        });
        this.eventSource.addEventListener('add', (event) => {
//处理数据
        });
        this.eventSource.addEventListener('finish', (event) => {
          this.scrollToBottom();
          this.eventSource.close()
        });
        this.eventSource.onerror('errorhandle', (error) => { 
          this.eventSource.close()
        });

注意: 如果后端配置的不是 'add' 那代码中的 'add'就要换成后端配置的event类型

fetch+SSE

    async handleEventStream(id) {
      this.controller = new AbortController();
      const response = await fetch(`https://XXXXXXXXXX`, {
        method: 'post',
        headers: {
          'Accept': 'text/event-stream',
          'Authorization': `Bearer ##############`
        },
        signal: this.controller.signal
      });

      if (!response.ok || !response.body) {
        throw new Error('SSE连接失败');
      }
      if (response.name === 'AbortError') {
        console.log('连接被主动终止');
      }

      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let buffer = '';

      while (true) {
        const { done, value } = await reader.read();
        if (done || this.controller.signal.aborted) {
          console.log('连接关闭');
          break;
        }

        buffer += decoder.decode(value, { stream: true });

        while (true) {
          const endIndex = buffer.indexOf('\n\n');
          if (endIndex === -1) break;

          const chunk = buffer.slice(0, endIndex);
          buffer = buffer.slice(endIndex + 2);
          
          const event = this.parseSSEEvent(chunk);
          if (event) this.handleEvent(event);
        }
      }
    },
    parseSSEEvent(rawData) {
      const event = {
        data: '',
        event: 'add'
      };

      rawData.split('\n').forEach(line => {
        const colonIndex = line.indexOf(':');
        if (colonIndex <= 0) return;
        
        const field = line.slice(0, colonIndex).trim();
        const value = line.slice(colonIndex + 1).trim();

        switch (field) {
          case 'data':
            event.data += value + '\n';
            break;
          case 'event':
            event.event = value;
            break;
        }
      });

      if (event.data.endsWith('\n')) {
        event.data = event.data.slice(0, -1);
      }

      return event;
    },
    handleEvent(event) {
      switch (event.event) {
        case 'add':
          this.handleAddEvent(JSON.parse(event.data.toString()))
          break;
        case 'images':
          this.handleImagesEvent(JSON.parse(event.data.toString()))
          break;
        case 'finish':
          this.handleFinishEvent()
          break;
        default:
          this.handleErrorHandleEvent()
      }
    },
    stopSSE() {
      if (this.controller) {
        this.controller.abort();
        this.controller = null;
      }
    },

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值