前端怎么用 EventSource并配置请求头及加参数(流式数据)

EventSource 接口是 web 内容与服务器发送事件通信的接口。
一个 EventSource 实例会对 HTTP 服务器开启一个持久化的连接,以 text/event-stream 格式发送事件,此连接会一直保持开启直到通过调用 EventSource.close() 关闭。
EventSource 服务器发送事件是单向的。数据消息只能从服务端发送到客户端。

一、EventSourcePolyfill

EventSourcePolyfill 是EventSource封装的一个方法,EventSourcePolyfill 可以配置请求头

// 安装
 npm install event-source-polyfill --save

//引用
import { EventSourcePolyfill } from "event-source-polyfill";

二、直接上代码

 sendRequest(messageId, content, questionId, questionType) {
      const innerIndex = this.messageList.length - 1;
      const aiToken = JSON.parse(localStorage.getItem('token'));

      let that = this;
      let eventSource;
      if (questionId) {
        eventSource = new EventSourcePolyfill(
          `${
            process.env.VUE_APP_WEB_API
          }/url...........?f_rnd=${new Date().getTime()}&message_id=${messageId}&question_id=${questionId}&stream=true`,
          {
            headers: {
              'Content-Type': 'text/event-stream',
              aiToken: aiToken,
              accept: '*/*',
              'Cache-Control': 'no-cache',
              Connection: 'keep-alive',
              // 'cache-control': 'max-age=0',
            },
          }
        );
      } else {
        eventSource = new EventSourcePolyfill(
          `${
            process.env.VUE_APP_WEB_API
          }/ai_assistant_chatdoc/receive_message?f_rnd=${new Date().getTime()}&message_id=${messageId}&stream=true`,

          {
            headers: {
              'Content-Type': 'text/event-stream',
              aiToken: aiToken,
              accept: '*/*',
              'Cache-Control': 'no-cache',
              Connection: 'keep-alive',
            },
          }
        );
      }
      //open:订阅成功(和后端连接成功)
      eventSource.onopen = function (e) {
        console.log(e, '连接刚打开时触发');
      };
      //message:后端返回信息,格式可以和后端协商
      that.messageQueue = []; //整个流式数据
      this.processing = false; //判断是否返回数据中

      let resultWord = '';
      let rowData = {};

      eventSource.onmessage = function (e) {
        const data = JSON.parse(e.data) || {}; //这里后端返回的是字符串所以目前我这边有转换
        console.log(data, data.data.content, Date.now());

        if (data.code === 200) {
          that.loading = false;
          that.scrollFlag = false;
          if (data.data.content === '[DONE]') { //流式结束了
            rowData = data.data;
          }
          that.messageQueue.push(data.data.content);

          if (that.processing) return;
          that.processing = true; 
          (async function processMessages() {
            while (that.processing) {
              // 改为无限循环
              let message;
              if (that.messageQueue.length > 0) {
                message = that.messageQueue.shift();

                if (message === '[DONE]') {
                  that.receiveMsg.source = rowData.source;
                  that.receiveMsg.sourceEdit = rowData.is_edit;
                  that.$set(that.messageList[innerIndex], 'message_id', rowData.message_id);
                  that.requestRecomme(messageId, innerIndex);
                } else {
                  resultWord += message;
                  console.log(resultWord, 'resultWord');
                  that.$set(that.messageList, innerIndex, {
                    type: 'right',
                    session_id: data.data.session_id,
                    message_id: data.data.message_id,
                    reply_id: data.data.reply_id,
                    message: resultWord,
                    source: [],
                    sourceEdit: [],
                    question: [],
                  });
                  that.receiveMsg = that.messageList[innerIndex];
                  that.chcekScroll();
                  that.executeScroll(!that.scrollFlag);
                }
                await new Promise(resolve => setTimeout(resolve, 30)); //30毫秒读取一下message
              } else {
                that.processing = false;
                await new Promise(resolve => setTimeout(resolve, 800)); //如果读取速度大于流式返回速度就等一下
              }
              if (that.messageQueue.length === 0 && message === '[DONE]') {
                break;
              }
            }
            that.processing = false;
          })();
        }
      };
      //  error:错误(可能是断开,可能是后端返回的信息)
      eventSource.onerror = function (e) {
        console.log(e, '连接无法打开时触发');
        eventSource.close(); // 关闭连接
        setTimeout(() => {}, 5000);
      };
    },

链接: https://blog.csdn.net/weixin_49066399/article/details/138713416

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值