前言
今天刷抖音看到一个与前端海量数据下载优化相关的问题(在大数据资源请求的时候,前端如果等待所有数据加载完,那么页面从请求到最终呈现内容,会有很长一段的空白期,如何优化响应速度呢,这就需要我们对响应数据做切片处理了),刚好学习了顺便对客户端请求数据的相关知识简单做了下总结复习
关于 Fetch
Fetch API 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应。它还提供了一个全局 fetch()
方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源
视频的内容是基于 fetch 展开做讲解的,这里我们也一样,先用 fetch 为案例降解,后续用 axios 以同样的思路再做一遍
首先我们看一下官网提供的一段代码
fetch('http://example.com/movies.json') .then(response => response.json()) .then(data => console.log(data)) 复制代码
这里我们发现 fetch 发送请求时里边有 2 个 then,有的同学可能会有疑问,毕竟现在大部分项目使用的请求库都是 axios ,实际上 axios 也有这两个过程,只不过 axios 在内部把第一步 .json()或者.text()
数据转化的过程处理掉了,直接返回了我们处理后的结果
关于请求过程
前面提到,在请求中第一个异步回调有两个数据处理的方法 json()和text() ,而这些方法的调用都有一个前提,就是必须等待请求头 header 传输完成后才可以调用
而后一个回调则是需要等待整个body传输完成后触发,这就意味着,如果body数据很大的话,那么等待响应就需要很长的时间
优化思路
既然等待整个body传输完再响应需要花很长时间,那么我们能不能在body传输的过程中就取到数据呢?就是传输一点用一点(即分片),答案是可以的,那么具体怎么做呢,请看下面
优化方法
fetch 方法在它的第一个响应体中提供了一个方法 getReader ,可以获取一个观察加载进度的对象,这个对象上又提供了一个read方法,可以异步的获取当前读取的数据内容(value 字节数组)和加载状态(done,未加载完成时为false,全部加载完成时为true),我们可以根据这个 done 的状态做一个递归,直到加载完成时一直去读取当前已加载好的数据进行处理
TextDecoder 文本解码器,用来处理文本数据
async function loadBody (url) { const res = await fetch(url) const reader = await res.body.getReader() let flag = false while(!flag) { const { value, done } = await reader.read() flag = done const decoder = new TextDecoder() // 文本解码器 decoder.decode(value) const text = decoder.decode(value) console.log(text); } } 复制代码
现在我们拿一个本地 txt 文件,在浏览器慢速3G模式下调用一下上面的方法看看效果
我们发现数据已经可以按照我们的期望做到分段加载了
但是细心的同学会发现现在还有一点小瑕疵,就是在切分点,由于字节的截取,很有可能在还原时造成乱码,这时就需要我们对这些切割点做特殊处理了,关于切割点如何优化处理,还有使用 axios 时如何分片,我们会在下一节在做详细讲解,敬请关注