前端处理流式数据

前端处理流式数据

前言

本篇文章为笔者开发过程中总结的关于前端处理后端流式接口返回的流式数据

示例

此处以仿gpt对话形式的发送消息函数为例,本次对话为一个包含提问和回答对象的数组

js 复制代码
async send() {

  // 生成新的对话框,并将其id赋值给Tid
  const Tid = this.messageIdCounter++

  // 复制Vue组件中的一些变量到本地变量
  // let _store = this.$store
  // 本次对话为一个包含提问和回答对象的数组
  let _Message = this.allMessages

  // 去除用户输入两端的空格(用作参数)
  this.userInput1 = this.userInput.trim()

  // 检查用户输入是否非空
  if (this.userInput.trim() !== '') {
    // 添加用户消息到对话中
    this.allMessages.push({
      id: this.messageIdCounter++,
      type: 'user',
      content: this.userInput.trim()
    });

    // 添加回答框到对话中
    this.allMessages.push({
      id: Tid,
      type: 'chatbot',
      content: ''
    });

    // 构建API请求的URL
    const url = '你的后端api'

    // 构建API请求的初始化参数
    const init = {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
        // 后端所需头
      },
      body: JSON.stringify({
        // 后端所需参数
      }),
    }

    try {
      // 发起异步网络请求
      const response = await fetch(url, init);

      // 检查网络响应是否成功
      if (!response.ok) {
        throw new Error(`HTTP error! Status: ${response.status}`);
      }

      // 获取响应体的数据读取器
      const reader = response.body.getReader();
      // 创建用于解码文本的解码器
      const decoder = new TextDecoder('utf-8');

      // 创建一个可读流
      const stream = new ReadableStream({
        async start(controller) {
          while (true) {
            // 从数据读取器中读取数据
            const { done, value } = await reader.read();

            // 如果读取完成,关闭控制器并退出循环
            if (done) {
              controller.close();
              break;
            }

            // 解码值并将其附加到指定ID的消息内容中
            const match = decoder.decode(value, { stream: true });
            if (match) {

			  // 此处以String拼接方式给对应的回答对象的内容拼接流式数据
              _Message[Tid].content = _Message[Tid].content + match + ''

              // 更新 Vuex 中的 streamingData 状态
              // _store.commit('updateStreamingData', dataValue);
            } else {
              // _store.commit('updateStreamingData', decoder.decode(value, { stream: true }));
            }
          }
        },
      });

      // 输出一条日志,表示流数据已接收完毕
      console.log('Full data');

    } catch (error) {
      // 捕获并打印任何网络请求错误
      console.error('Fetch error:', error);
    }

    // 清空用户输入
    this.userInput = '';
  }

  // 打印所有消息
  console.log(this.allMessages)
},

流程说明

  1. 生成新的对话框: 通过递增 messageIdCounter 变量,生成新的对话框的 ID,并将其赋值给 Tid 变量。

  2. 复制变量: 复制 Vue 组件中的一些变量到本地变量 _Message。

  3. 处理用户输入: 去除用户输入两端的空格,将处理后的用户输入保存在 userInput1 变量中。

  4. 检查用户输入非空: 如果用户输入不为空,执行以下操作:

  5. 添加用户消息: 向对话中添加用户输入的消息,包括消息的 ID、类型为 'user',以及去除两端空格后的内容。

  6. 添加聊天机器人回答框: 向对话中添加一个新的聊天机器人回答框,包括消息的 ID、类型为 'chatbot',初始内容为空。

  7. 构建API请求: 构建发送到后端的 API 请求的 URL 和初始化参数。

  8. 发起网络请求: 使用 fetch 函数发起异步网络请求,等待响应。

  9. 处理网络响应: 如果网络响应不成功,抛出错误。如果成功,获取响应体的数据读取器,用于处理流式数据。

  10. 处理流式数据: 创建一个可读流,循环读取数据,解码数据并将其附加到聊天机器人回答框的内容中。在这里,使用 String 拼接方式,将流式数据追加到聊天机器人回答框的内容。

  11. 输出日志: 输出一条日志,表示流数据已接收完毕。

  12. 捕获网络请求错误: 如果发生网络请求错误,捕获错误并输出错误日志。

  13. 清空用户输入: 无论是否成功,最终都清空用户输入。

  14. 打印所有消息: 输出当前所有对话框的消息内容,以便进行调试和查看结果。

注意

上方代码中提供了两种前端流式输出数据的方法,其中未被注释的是通过String拼接的方式;被注释掉的是通过更新vuex的方式

相关推荐
dy171716 分钟前
element-plus表格默认展开有子的数据
前端·javascript·vue.js
2501_915918414 小时前
Web 前端可视化开发工具对比 低代码平台、可视化搭建工具、前端可视化编辑器与在线可视化开发环境的实战分析
前端·低代码·ios·小程序·uni-app·编辑器·iphone
程序员的世界你不懂4 小时前
【Flask】测试平台开发,新增说明书编写和展示功能 第二十三篇
java·前端·数据库
索迪迈科技4 小时前
网络请求库——Axios库深度解析
前端·网络·vue.js·北京百思可瑞教育·百思可瑞教育
gnip5 小时前
JavaScript二叉树相关概念
前端
attitude.x5 小时前
PyTorch 动态图的灵活性与实用技巧
前端·人工智能·深度学习
β添砖java6 小时前
CSS3核心技术
前端·css·css3
空山新雨(大队长)6 小时前
HTML第八课:HTML4和HTML5的区别
前端·html·html5
猫头虎-前端技术6 小时前
浏览器兼容性问题全解:CSS 前缀、Grid/Flex 布局兼容方案与跨浏览器调试技巧
前端·css·node.js·bootstrap·ecmascript·css3·媒体