当前位置: 首页 > article >正文

编程技巧:VUE 实现接口返回数据的流式处理

一、写在前面

ChatGPT 的问答响应界面相信大家都见过,内容是一点一点追加式的显示。不是等好了一起发给你,然后一次性展示出来。这种效果和我们平常开发的展示渲染模式有点区别。可能有的同学会说,前端拿到报文后,我们做成这样的效果不就行行了,有什么难的。
这话看起来很对,但其实不那么对。试想一下,如果一个问答内容响应体很大,几十上百兆,等报文传输完了,我们再显示,中间界面等待的时间会很长,体验其实是很差。
那有什么办法能加速在大报文的场景下,能加速前端界面渲染效果呢?

二、传统式交互

const url ='http://ip:port/path';
async function getResponse(){
    const resp = await fetch(url,{
        method : 'GET',
    });
    console.log('123');
    const data = await resp.text();
    console.log(data);
}
getResponse();

直接从HttpResponseBody中直接一次性获取服务端的响应内容是传统式编程开发。

三、流式传输交互

我们都知道网络传输其实并不是一次性发送所有报文,其实是一部分一部分的传输。也就是说服务端网络是一部分一部分,客户端网络也是一部分一部分接收的,然后拼在一起拿出来的。
那我们有没有办法传输一部分的时候我们就直接一部分的一部分,不用等全部传完我们再拿呢?答案是有的。

const url ='http://ip:port/path';
async function getResponse(){
    const resp = await fetch(url,{
        method : 'GET',
    });
    // 获取 response 读取器
    const reader = resp.body.getReader();
    // 创建一个文本解码器
    const decoder = new TextDecoder();
    while (1){
        // 一块一块读
        // done 代表读完了没有,value代表此次读的内容是啥
        const {done,value} = await reader.read();
        const text = decoder.decode(value)
        console.log(done);
        console.log(text)
        if(done){
            break;
        }
    }
}


如此我们就能提前拿到报文,不需要等报文都传输完再获取。这样加快了前段渲染出数据的速度,而且也达到了ChatGPT那种一点一点追加式显示的效果。

四、监控响应进度

前端实现 Ajax 无非两种做法,一种是XHR,这个API比较老,也比较传统,也是至今用的最广的一种。一种是Fetch,是一种比较新的API。这些都是浏览器的原生能力,我们要知道,原生能力都做不到的话,第三方库也是做不到的。axios 是基于 XHR实现的,umi-request 是基于 Fetch 实现的。原生是能力的边界,第三方库也只能在边界里面玩,这是定数。


上图是这两种 API 原生能力支持的对比说明。
我们现在要实现监控响应进度,那么XHR和Fetch都是能实现的。
如果要做请求进度监控,比如上传进度监控,监控客户端的报文是否都给了服务端,无可厚非,只能选择XHR或者axios。

五、Fetch 监控响应进度实现

const url ='http://ip:port/path';
async function getResponse(){
    const resp = await fetch(url,{
        method : 'GET',
    });
    const total = +resp.headers.get('content-length');
    let body = '';
    let loaded = 0;
    // 获取 response 读取器
    const reader = resp.body.getReader();
    // 创建一个文本解码器
    const decoder = new TextDecoder();
    console.log(total);
    while (1){
        // 一块一块读
        // done 代表读完了没有,value代表此次读的内容是啥
        const {done,value} = await reader.read();
        if(done){
            break;
        }
        loaded += value.length;
        const text = decoder.decode(value)
        body += text
        console.log(loaded);
        // console.log(body);
        // console.log(done);
        // console.log(text)
    }
}
getResponse();

上面方法是通过读取response的header头中content-length 属性获取报文总大小,然后计算每次获取的量,这样就达到了监控响应进度的目的。

六、XHR 监控响应进度实现

const url ='http://ip:port/path';
async function getResponse(){
    const xhr = new XMLHttpRequest();
    // 监听读取内容状态变更事件
    xhr.addEventListener('readystatechange',()=>{
        // 当都读取状态为结束时
        if(xhr.readyState === xhr.DONE){
            // 完整报文
            console.log(xhr.responseText);
        }
    });
    // 监听进度事件
    xhr.addEventListener('progress',(e)=>{
        console.log(e);
    });
    xhr.open('GET',url);
    xhr.send();
}
getResponse();

XHR是事件类型的 API 风格,是通过监听 xhr 不同的事件来达到获取进度的目的。

七、响应进度监控的特例

上面不论是Fetch API 还是 XHR API 都不是百分百可行的。在开启服务端 nginx 的 gzip 压缩时,两种获取进度的能力将全部失效。无法在传输的过程中获取到报文的总大小或者 response 的 header 头中无 content-length 属性。
在Http 1.0及之前版本中,content-length字段可有可无。
在http1.1及之后版本,如果是 keep alive,如果存在Transfer-Encoding(重点是chunked),则在header中不能有Content-Length,有也会被忽视。 content-length 和 Transfer-Encoding:chunked 必然是二选一。若是非keep alive,则和http1.0一样。content-length可有可无。
在nginx开启gzip压缩时,则 response 的 header 头中存在的是 Transfer-Encoding:chunked,则不会存在 content-length。
所以在这种情况下,无法实现报文相应进度监控,但是能持续获取到报文的大小已传输的大小


http://www.kler.cn/a/545991.html

相关文章:

  • FPGA实现SDI视频缩放转GTY光口传输,基于GS2971+Aurora 8b/10b编解码架构,提供工程源码和技术支持
  • 网络安全 | 网络攻击介绍
  • 【项目日记(五)】第二层: 中心缓存的具体实现
  • 释放你的元数据:使用 Elasticsearch 的自查询检索器
  • 大中型企业专用数据安全系统 | 天锐蓝盾终端安全 数据安全
  • 深入理解DOM:22个核心知识点与代码示例
  • ‌CBA认证‌(业务架构师认证)简介---适用人群、考试内容与形式、含金量与职业前景,以及‌CBA、TOGAF认证对比表格
  • Vulnhub靶机渗透-DC5
  • 一款利器提升 StarRocks 表结构设计效率
  • 微信小程序地图标记点,安卓手机一次性渲染不出来的问题
  • 每日一题——矩阵最长递增路径
  • 基于Linux系统理解 IO文件系统
  • 中间件系列--【运维手册规范】
  • 用java实现word(docx)转换为pdf格式文档(简单版)
  • Linux Mem -- MTE in AArch64 Linux
  • CTF-WEB: 利用iframe标签利用xss,waf过滤后再转换漏洞-- N1ctf Junior display
  • 微信小程序实战项目001:NBA球队太阳队简介
  • 掌控系统性能的利器:自动化系统性能监控工具
  • 成本哪个更低更好用?分析对比大模型OCR、传统OCR和深度学习OCR
  • RabbitMQ配置SSL证书