评论

小程序实现流式数据(打字机)效果输出

小程序实现ai流式数据输出实现

小程序实现打字机流式数据输出,有两种方案,一种就是小程序自身实现,另外一种就是使webView转接到 h5 间接实现。

小程序自身实现就是用 uni.request 的 enableChunked 分块数据配置项

const requestTask = uni.request({
    url: '服务地址',
   timeout: 100000,
   responseType: 'text',
   method: 'GET',
   enableChunked: true, //配置这里
   data: {},
})

// 返回的 requestTask  拥有一个 onChunkReceived 监听回调
onChunkReceived 的回调参数:
res:data (ArrayBuffer):接收到的分块数据。

requestTask.onChunkReceived(res => {
  // res 流式数据  注意:这里可能是多块数据,服务推送多次信息,onChunkReceived只响应一次,则该次监听的内容就是服务器推送多次拼接在一起的字符串,需要单独裁剪额外处理
  try {
    // 解码分块数据
    const uint8Array = new Uint8Array(res.data);
   let test = String.fromCharCode.apply(null, uint8Array);
   test = decodeURIComponent(escape(test));
   let testArr = test.split('data:');
    console.log(testArr, '====9999===');  // 这里就是服务器推送的原始内容
    // 后续用户自己的操作。。。
  }
  catch(err){
   console.error('推送数据结构异常!', err); 
 }
})

requestTask.abort() // 手动关闭链接


webView转接到 h5 间接实现

使用 h5 内嵌的话,那就正常跟 web端实现一样,使用 EventSource(单项数据流) 实例(因为小程序端没有 EventSource 实例,所以不可用),EventSource 方案只支持 get 请求,所以传参可能会复杂些

let eventSource = new EventSource('服务链接+传参');

eventSource.onopen = (e) => { 
  // 链接建立成功的钩子
}

eventSource.onerror= (e) => { 
  // 链接异常抛出的钩子
}

eventSource.onmessage = (e) => { 
  //  服务端推送信息捕获的钩子,服务端推送一次就会触发一次  https://developer.mozilla.org/zh-CN/docs/Web/API/EventSource/EventSource
}

eventSource.close() // 手动关闭链接

最后一次编辑于  03-04  
点赞 2
收藏
评论

4 个评论

  • 浪味仙
    浪味仙
    08-22

    看了好多流式数据解码那块的逻辑,解码出来都有部分乱码,目前您这个没有这个情况! 膜拜啊!

    08-22
    赞同
    回复
  • 仲钟十五
    仲钟十五
    07-14

    我用onChunkReceived,是直接不会进入这个方法里,这是为什么啊,我也设置了enableChunked,后端也设置了header('Transfer-Encoding: chunked');

    07-14
    赞同
    回复
  • 艺术家小锃子
    艺术家小锃子
    07-01

    请问有发现真机onChunkReceived后台数据丢失的问题吗?我现在遇到了,没找到解决办法。

    07-01
    赞同
    回复 3
    • 烬明
      烬明
      07-02
      onChunkReceived 返回的回调内容可能包好了多段流式数据,而你拼接的时候应该是按照一段拼接的,你打印一下 onChunkReceived  返回的 res 就知道了,缺失数据当时我也碰到了
      07-02
      回复
    • 冷暖自知🍃
      冷暖自知🍃
      07-07回复烬明
      目前偶尔会丢失 一 两个字 的问题遇到过吗?
      07-07
      回复
    • 如日
      如日
      08-27
      可以考虑一下,真机连接的后端的相关sse接口有没有禁用nginx缓存,需要手动禁用缓存。可以参考:
      # 设置 Nginx 不对 SSE 响应进行缓冲,直接透传给客户端
      proxy_buffering off;
      # 设置代理读取服务器响应的超时时间
      proxy_read_timeout 24h;
      # 设置客户端连接的超时时间
      proxy_connect_timeout 1h;
      # 设置 HTTP 版本,SSE 需要 HTTP/1.1
      proxy_http_version 1.1;
      # 保持连接活性,不发送连接关闭的信号
      proxy_set_header Connection '';
      # 配置代理传递的头部,确保 Host 头部正确传递
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      # 设置代理的响应头部,保持传输编码为 chunked
      proxy_set_header X-Accel-Buffering no;
      # 设置流式响应头
      proxy_set_header Accept "text/event-stream";
      proxy_set_header Cache-Control "no-cache";
      # 禁用压缩
      proxy_set_header Accept-Encoding "";
      # 设置跨域资源共享 (CORS)
      add_header 'Access-Control-Allow-Origin' '*' always;
      add_header 'Access-Control-Allow-Credentials' 'true' always;
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
      add_header 'Access-Control-Allow-Headers' 'Origin,Authorization,Accept,X-Requested-With,Content-Type' always;
      08-27
      回复
  • 查查
    查查
    06-20

    webView转接到 h5 间接实现 在正式版不行 体验版可以

    

    06-20
    赞同
    回复 1
    • 烬明
      烬明
      06-30
      是不是对应的业务域名在后台没配置
      06-30
      回复
登录 后发表内容