前端基于SSE实现类似GPT打字机效果

WHAT

Server-Sent Events(以下简称SSE)是一种用于实现服务器向客户端实时推送数据的Web技术。与传统的轮询和长轮询相比,SSE提供了更高效和实时的数据推送机制。

SSE基于HTTP协议,允许服务器将数据以事件流(Event Stream)的形式发送给客户端。客户端通过建立持久的HTTP连接,并监听事件流,可以实时接收服务器推送的数据。

SSE的主要特点

  1. 简单易用:SSE使用基于文本的数据格式,如纯文本、JSON等,使得数据的发送和解析都相对简单。
  2. 单向通信:SSE支持服务器向客户端的单向通信,服务器可以主动推送数据给客户端,而客户端只能接收数据。
  3. 实时性:SSE建立长时间的连接,使得服务器可以实时地将数据推送给客户端,而无需客户端频繁地发起请求。

SSE与WebSocket的比较

WebSocket是另一种用于实现实时双向通信的Web技术,它与SSE在某些方面有所不同。下面是SSE和WebSocket之间的比较:

  1. 数据推送方向:SSE是服务器向客户端的单向通信,服务器可以主动推送数据给客户端。而WebSocket是双向通信,允许服务器和客户端之间进行实时的双向数据交换。
  2. 连接建立:SSE使用基于HTTP的长连接,通过普通的HTTP请求和响应来建立连接,从而实现数据的实时推送。WebSocket使用自定义的协议,通过建立WebSocket连接来实现双向通信。
  3. 兼容性:由于SSE基于HTTP协议,它可以在大多数现代浏览器中使用,并且不需要额外的协议升级。WebSocket在绝大多数现代浏览器中也得到了支持,但在某些特殊的网络环境下可能会遇到问题。
  4. 适用场景:SSE适用于服务器向客户端实时推送数据的场景,如股票价格更新、新闻实时推送等。WebSocket适用于需要实时双向通信的场景,如聊天应用、多人协同编辑等。

前端基于SSE实现类似GPT打字机效果

安装

npm install @microsoft/fetch-event-source --save

使用

<script>
import { fetchEventSource } from '@microsoft/fetch-event-source'
export default {
  data() {
    return {
      controller: null
    };
  },
  methods: {
    onSend() {
      // 业务逻辑
      this.sendSSEMessage(param, '内容')
    },
    sendSSEMessage(param, userQuery) {
      let message = ''
      let getFirst = false // 是否为收到的第一条消息
      let hasDone = false // 消息结束
      if (!this.controller) {
//信号对象,可以用来取消与Fetch API相关的操作
        this.controller = new AbortController()
        const signal = this.controller.signal
        fetchEventSource('流式接口路径', {
          method: 'POST',
          signal: signal,
          headers: {
            "Content-Type": 'application/json'
          },
          body: JSON.stringify(param),
// openWhenHidden: 监听visibilitychange,当页面不可见时关闭连接,当页面重新可见时重新打开连接
          openWhenHidden: true,
          onmessage: (event) => {
            let data = null
            try {
              data = JSON.parse(event.data);
            } catch (error) {
              console.log('parse error')
            }
            if(data){
              if (data.code == '-1') {// 根据实际返回的数据判断
                console.log('请求失败')
                this.closeCtrl()
              } else if (hasDone) {
                // 结束
                this.closeCtrl()
              } else {
                if (!getFirst) {
                  getFirst = true
                  message += data.content // 拼接字符串
                  // 这边可以修改展示内容
                }
              }
            }
            if (event.data == '[DONE]') {
              hasDone = true
            }
          },
          onerror: (err) => {
            console.log('SSE抛出异常')
            this.closeCtrl()
            throw err;
          },
          onclose: () => {
            this.closeCtrl()
          }
        })
      }
    },
    closeCtrl() {
      /**
       * 取消fetch请求,一般在以下场景应当关闭
       * 1、接收到与后端约定的含有错误标识的消息
       * 2、结束会话
       * 3、在页面离开时,丢弃未完成的请求
       * 4、连接出现异常回调
       * 
       * 注意:abort方法可以被多次调用,但第二次及以后的调用不会有任何效果。一旦请求被取消,它将保持取消状态。
       */
  
      if (this.controller) {
        this.controller.abort()
        this.controller = null
      }
    },
  },
  beforeDestroy() {
    this.closeCtrl()
  },
};
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熬夜不秃头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值