vue2 纯前端实现像chatGpt一样的笔墨流式输出 [复制链接]
发表于 2025-10-30 12:36:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1、先展示一下效果啦
   笔墨流输出
2、起首确定接口返回的是字符串,那就先调取接口
  1. // 由于需求关系 有很多个文本需要一起逐字输出 所以这里就采用了Promise.all的形式
  2. async getThreeTextarea() {
  3.         let taskArray = [ "重点项目文本","应用领域文本", "用途文本","成果需求文本", "问题描述","建议描述",]
  4.         await Promise.all(taskArray.map((task, index) => {
  5.         // 这里调取接口
  6.                 const promise = this.getContentThree(this.orderId, task, index);
  7.         // 这里是为取消行为做准备
  8.                 this.streamThreePromises.push(promise);
  9.                 return promise;
  10.         }));
  11. },
  12. async getContentThree(id,task,index) {
  13.     // 如果取消了 就停止请求接口
  14.         if (!this.cancelTokenSource) return
  15.         let response = await axios.post(`${home}/model/workflowsIndexThree`, {
  16.                 id: id,
  17.                 taskt: task,
  18.         }, {
  19.         // axios提供的取消请求的示例
  20.                 cancelToken: this.cancelTokenSource.token
  21.         });
  22.         if (typeof response.data !== 'string') return
  23.     // 将字符串中的\n和\n\n都替换成<br>标签
  24.         let formattedData = response.data.replace(/\n\n/g, '<br>').replace(/\n/g, '<br>');
  25.     // 赋值给对应的字段
  26.         let contentLabels = ['zdxmycText', 'yylyycText', 'ytycText', 'cgxqycText', 'wtzjText', 'jyzjText']
  27.         let contentProperty = contentLabels[index]
  28.         if (!contentProperty) return
  29.     // 这里就开始调用 逐字输出的方法啦
  30.         const promise = this.streamTextUpdate(contentProperty, formattedData);
  31.         this.streamThreePromises.push(promise);
  32.         await promise;
  33. },
  34. async streamTextUpdate(contentProperty, data) {
  35.         if (typeof data !== 'string') {
  36.                 data = JSON.stringify(data) || '';
  37.         }
  38.         let text = "";
  39.     // 遍历字符串 然后每加一个字符就更新一下视图
  40.         for (let i = 0; i < data.length; i++) {
  41.                 if (this.streamCancellationToken) {
  42.                         break;
  43.                 }
  44.         // String.charAt(index)是找到指定索引的字符 类似于Array[index]
  45.                 text += data.charAt(i);
  46.                 this.$set(this, contentProperty, text);
  47.                 await this.$nextTick();
  48.         // 每隔50毫秒输出一个字符
  49.                 await new Promise(resolve => setTimeout(resolve, 50));
  50.         }
  51. },
  52. // 提示取消操作 嫌啰嗦 其实可以不要
  53. handleBeforeUnload(event) {
  54.         if (this.cancelTokenSource) {
  55.                 this.cancelTokenSource.cancel('中断操作');
  56.         }
  57.         this.streamCancellationToken = true;
  58.         this.streamThreePromises.forEach(promise => {
  59.                 if (promise.cancel) {
  60.                         promise.cancel();
  61.                 }
  62.         });
  63.         const message = '正在关闭页面,未完成的操作将被取消。';
  64.         return this.$message.warning(message)
  65. },
复制代码
3、获取完数据就可以将数据渲染上去了
  1. <div class="fx-content" style="height: 300px;overflow-y: auto;" v-html="zdxmycText"></div>
复制代码
4、渲染乐成后,假如笔墨流输出还没有遍历完 就关闭页面,这时间就出现一个标题,当你在打开的时间,笔墨就会像蹦迪一样(忽闪忽闪的)这时间就用到了 我们刚刚提到取消哀求和停止输出
 页面初始化时
  1. if (!this.cancelTokenSource) {
  2.     // 在页面初始化的时候 就实例化一下取消请求的实例
  3.     this.cancelTokenSource = axios.CancelToken.source();
  4.     // 监听是否要取消操作
  5.         window.addEventListener('beforeunload', this.handleBeforeUnload.bind(this));
  6. }
  7. this.streamCancellationToken = false;
复制代码
 页面烧毁时
  1. // 在页面销毁的时候 取消监听
  2. window.removeEventListener('beforeunload', this.handleBeforeUnload.bind(this));
  3. if (this.cancelTokenSource) {
  4.     this.cancelTokenSource.cancel('中断操作');
  5. }
  6. this.streamCancellationToken = true;
  7. // 然后取消所有的promise
  8. this.streamPromises.forEach(promise => {
  9.     if (promise.cancel) {
  10.                 promise.cancel();
  11.         }
  12. });
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表