一比一实现ChatGPT流式接口前端显示效果(打字机效果)【对比几种不同的流式实现方案】

前端实现GPT或者其他大模型的流式推送的数据接收可以通过EventSourceAxios、或者基于EventSource实现的@microsoft/fetch-event-source插件库;

GPT官方是基于原生EventSource实现的流式数据接收,我们作为个人开发使用可以使用Axios或者使用@microsoft/fetch-event-source插件库,后两种可以携带header并且操作接口请求参数格式较为自由

话不多说,直接开始(注:以下代码基于vue)

方案一 EventSource

javascript 复制代码
sendSSEMessage() {
      // 只有当eventSource不存在时才创建新的EventSource连接
      if (!this.eventSource) {
        this.messages.push({text: this.inputText, isMine: true});
        this.messages.push({text: "", isMine: false});

        // 创建新的EventSource连接
        this.eventSource = new EventSource('http://127.0.1.1:8383/completions?messages='+this.inputText);

        // 设置消息接收的回调函数
        this.eventSource.onmessage = (event) => {
          const data = JSON.parse(event.data);
          this.messages[this.messages.length - 1].text += data.choices[0].delta.content;
        };

        // 可选:监听错误事件,以便在出现问题时能够重新连接或处理错误
        this.eventSource.onerror = (event) => {
          console.error("EventSource failed:", event);
          this.eventSource.close(); // 关闭出错的连接
          this.eventSource = null; // 重置eventSource变量,允许重建连接
        };
      }
    }

异常处理和重连 处理连接中断或其他异常也是至关重要的。你可能需要在失去连接时尝试重新连接,或者至少提醒用户当前的连接状态。这可以通过监听EventSource的错误事件并采取适当的行动来实现。 如果需要携带header或者其他参数可以考虑使用更完善的插件库@microsoft/fetch-event-source,我自己开发的GPT4.0网站也是基于这个插件库实现的, 这里给自己网站打个广告--->>欢迎各位看官老爷点击这里参观

--重回正题--

方案二 @microsoft/fetch-event-source插件库(更好用的SSE库)

1.首先从@microsoft/fetch-event-source中引入fetchEventSource

javascript 复制代码
import { fetchEventSource } from '@microsoft/fetch-event-source';
javascript 复制代码
   async sseSendStream(){
   			let that = this
            let token = "获取token";
            let tokens = "Bearer" + ' ' + token;

            let params =  {
                "model": that.gptmodel,
                "stream": true,
                "convGroupId": that.convGroupId,
                "parentConvId": that.convId,
                "request": that.inputText,
            }
            that.inputText = ""; //发送请求前将输入清空
            return new Promise((resolve, reject) => {
                try {
                    let concateContent = "";
                    fetchEventSource(url, {
                        method: 'post',
                        headers: {
                            'Content-Type': 'application/json',
                            "Accept": "text/event-stream",
                            "Authorization": tokens,
                        },
                        responseType: 'text/event-stream',
                        body: JSON.stringify(params),
                        signal: that.controller.signal,
                        openWhenHidden: true,
                        async onopen(response) {//建立连接的回调},
                        onmessage(msg) {//接收一次数据段时回调,因为是流式返回,所以这个回调会被调用多次
                            if(msg.event==''){
                                //进行连接正常的操作
                                try{
                                    const dataObj = JSON.parse(msg.data)
                                    // 检查数据块是否包含有效的content字段
                                    if (dataObj) {
                                        // 将content字段的值拼接到结果字符串中
                                        concateContent += dataObj.choices[0].delta.content;
                                        that.dialogueList[that.dialogueList.length - 1].text = concateContent
                                    }
                                }catch (e){
                                }
                            }else if (msg.event === 'close') {
                                //连接错误的操作
                                reject('close error')
                            }
                        },
                        onclose() {//正常结束的回调
                           //在这里写一些GPT回答结束后的一些操作
                        },
                        onerror(err) {//连接出现异常回调
                            // 取消请求
                            reject(err); // 发生错误,拒绝 Promise
                            throw err
                        },
                    })
                } catch (e) {
                    reject(e); // 拒绝 Promise
                }
            });
        },
  1. 通过 fetchEventSource(url, {...}) 发送 SSE 请求。
  2. 传递给 fetchEventSource 的参数包括请求的方法、头部信息、请求体、信号等
  3. onopen(response):建立连接时的回调函数。
  4. onmessage(msg):接收到数据时的回调函数。由于 SSE 是流式传输,所以这个回调函数会被多次调用。在这个回调函数中,首先检查是否发生了用户手动取消请求的情况,然后根据消息的类型进行相应的处理
  5. onclose():正常结束连接时的回调函数。
  6. onerror(err):连接出现异常时的回调函数。
  7. onmessage 回调函数中,根据接收到的消息进行相应的处理。如果消息类型为空字符串,则表示连接正常,对数据进行解析和处理;如果消息类型为 'close',则表示连接错误

axios方案暂时先不写了,还是更推荐上面两种正儿八经的SSE推送接收方案,希望各位都能用上接的大模型, 也可以直接访问我的半公益网站使用GPT,点我嗷...(呸,又一次广告....)

相关推荐
一路向北he2 分钟前
字节钢铁军团--“提供情境,而非控制”
java·开发语言·前端
kyriewen24 分钟前
豆包和千问同时关了智能体,我用它们搭的 3 个自动化全废了——迁移方案整理
前端·javascript·ai编程
前端一小卒38 分钟前
我用 TypeScript 从零手写了一个 Claude Code,然后发现它的核心只有 30 行
前端·agent
大圣编程2 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang2 小时前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆3 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜3 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
负责的蛋挞5 小时前
异步HttpModule的实现方式
java·服务器·前端
丹宇码农7 小时前
把 HLS 字幕玩出花:zwPlayer 如何让 M3U8 视频支持全文搜索、翻译与码率自适应
前端·javascript·音视频·hls·视频播放器