m0_37508779 2024-12-05 15:08 采纳率: 0%
浏览 26

微信小程序-关于ai回复时输出内容过长时,使用setdata输出时,会导致小程序卡顿,有好的解决方法吗?

微信小程序-关于ai回复时输出内容过长时,使用setdata输出时,会导致小程序卡顿,有好的解决方法吗?

requestTask.onChunkReceived(function (response) {
      const arrayBuffer: any = response.data;
      let responseText = '';
      const uint8Array: any = new Uint8Array(arrayBuffer);
      let text = String.fromCharCode.apply(null, uint8Array);
      responseText += text;
 
      const lastIndex = responseText.lastIndexOf('\n', responseText.length - 2)
      let chunk = responseText
      let chunkArr = []
      if (lastIndex !== -1) {
        let linesArray: any = responseText.split('\n');
        chunkArr = linesArray.filter((item: any) => item !== '');
      } else {
        chunkArr.push(chunk)
      }
      try {
        let stopStatus = _this.data.stopStatus
        if (stopStatus) {
          _this.setrestart()
          requestTask.abort(); // 终止请求
        }else{
          let replysources: any = _this.data.replysources
          let index = replysources.length - 1;
          replysources[index].text = replysources[index].text + text
          //markdown '#1E1E1E'
          replysources[index].textmarkdown = app.towxml(replysources[index].text, 'markdown', {
            theme:'dark'
          })
          _this.setData({
            replysources: replysources,
            process_status: true, //表示进程正在继续
          })
        }
      }
      catch (error) {
        //
        console.log("error1:", error)
      }
    })

上述是接收返回数据,并通过setdata进行输出,但是返回的内容过长,点击停止输出时,不能响应。返回的内容少,点击停止时能快速响应的,请问下有没有好的解决方法吗?

  • 写回答

1条回答 默认 最新

  • 越重天 新星创作者: Java技术领域 2024-12-05 19:11
    关注

    本答案参考 多次询问 ChatGPT-3.5 后选择的最佳回答,若是满意,还请采纳,谢谢

    当使用setData输出过长内容导致小程序卡顿以及点击停止输出不能及时响应时,可以考虑以下解决方法:

    1. 数据分块处理

      • 不要一次性将大量数据通过setData更新到视图层。可以将长文本数据分割成较小的块,然后逐步更新视图。例如,按照一定的字符数量或者语义单元进行分割,每次只更新一部分数据。
      • 在代码中,可以修改数据处理逻辑,比如在获取到长文本数据后,定义一个函数来切割数据块:
      function splitDataIntoChunks(data, chunkSize) {
        let chunks = [];
        for (let i = 0; i < data.length; i += chunkSize) {
          chunks.push(data.slice(i, i + chunkSize));
        }
        return chunks;
      }
      

      然后在onChunkReceived函数中,按照块来更新数据,而不是直接将整个长文本拼接后更新。

    2. 节流或防抖处理点击事件

      • 对于点击停止输出的按钮,可能由于频繁触发setData导致事件队列堵塞,无法及时响应。可以使用节流(throttle)或者防抖(debounce)技术。
      • 例如,使用lodash库中的节流函数(如果在小程序项目中允许引入外部库):
      import throttle from 'lodash.throttle';
      
      // 在Page对象的外面定义节流后的函数
      const throttledStopFunction = throttle(() => {
        // 这里是停止输出的实际逻辑,例如修改相关数据状态来停止数据获取和更新
      }, 300);
      
      // 在按钮的点击事件中调用节流后的函数
      Page({
        //...
        stopOutput: function() {
          throttledStopFunction();
        }
      });
      

      防抖的原理类似,只是触发时机稍有不同。防抖是在事件停止触发一段时间后才执行函数,而节流是在一定时间间隔内只执行一次函数。

    3. 优化setData的使用

      • 只更新setData中真正改变的部分数据。在你的代码中,每次更新replysources时,可能不需要更新整个数组对象。如果只是其中某个元素的text或者textmarkdown改变,可以只更新这个元素,而不是整个数组。例如:
      let newReplySource = replysources[index];
      newReplySource.text = newReplySource.text + text;
      newReplySource.textmarkdown = app.towxml(newReplySource.text,'markdown', {
        theme: 'dark'
      });
      _this.setData({
        [`replysources[${index}]`]: newReplySource,
        process_status: true
      });
      
      • 同时,尽量减少不必要的数据嵌套,因为setData在更新嵌套较深的数据时效率可能会降低。
    4. 使用wx.createSelectorQuery进行视图更新优化

      • 当数据更新后,视图的渲染可能会比较耗时。可以使用wx.createSelectorQuery来更精准地控制视图的更新范围。例如,如果只是某个特定的组件需要根据新数据重新渲染,可以通过选择器定位到这个组件,然后进行局部更新,而不是让整个页面重新渲染。
      wx.createSelectorQuery().select('#specific - component - id').boundingClientRect(function(rect) {
        // 根据rect获取组件的相关信息,如位置、大小等
        // 然后根据新数据进行局部更新操作
      }).exec();
      
    5. 考虑使用虚拟列表(针对长列表情况,如果相关)

      • 如果返回的数据是一个长列表,并且在视图中以列表形式展示,可以采用虚拟列表的技术。虚拟列表只渲染可视区域内的列表项,而不是一次性渲染所有的列表项。这样可以大大减少视图渲染的负担,提高性能。虽然你的情况是长文本,但如果文本展示方式类似列表(例如每行是一个元素),也可以借鉴这种思路。
    6. 数据预加载和缓存策略优化

      • 如果数据是重复获取的,可以考虑添加缓存机制。例如,使用Map对象来存储已经获取过的数据,下次请求时先检查缓存中是否存在,如果存在则直接使用缓存数据,而不需要再次从网络获取和处理。
      • 对于预加载,可以根据用户的操作习惯或者业务逻辑,提前加载部分数据,避免在用户点击操作时一次性加载大量数据导致卡顿。
    评论

报告相同问题?

问题事件

  • 创建了问题 12月5日