前段时间做了loading动画,增加用户体验,不至于请求时间误认为程序卡死。后来发现当网络不好或者数据过大时,请求时间比较长,没有返回完结果之前,loading一直在加载,于是改做成百分比显示进度,让客户实时感觉到程序在运行。就像下面这样。
本文用两种请求方法 'Xhr' 和 'fetch' ,来实现这个功能。
Xhr方法
用Xhr发请求,响应进度是比较容易获取的,因为JS官方提供一个监听函数“progress”,用来对响应进度进行监听。这个方法接收一个对象,我们用到里面的两个属性,total: 表示正在执行的底层流程的工作总量,也就是总响应数据的长度,loaded: 表示底层流程已经执行的工作总量,也就是已经加载的响应数据的长度。通过这两个属性,就可以计算出来响应进度的百分比。
fetch方法
用fetch方法也是一样,只要获取到total和loaded就可以。但是fetch没有监听函数,要换另一种方法:先通过请求头获取到 content-length 总长度,再用数据流的API body.getReader 获取响应体已经加载好的长度,通过这两个数据,也可以计算出来响应进度百分比。
直接上代码:
// node服务代码
const express = require("express");
const fs = require("fs");
const path = require("path");
const app = express();
// 设置跨域访问
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type");
next();
});
// test.js文件与当前node服务平级,随便const一个字符串,复制内容长一点
const filePath = path.join(__dirname, "test.js");
app.get("/test", (req, res) => {
fs.readFile(filePath, (err, data) => {
// 设置Content-Type为text/javascript
res.setHeader("Content-Type", "text/javascript");
res.send(data);
});
});
// 设置服务器监听端口
const port = 3000;
app.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});
前端代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
<el-button @click="visible1" type="success">xhr</el-button>
<el-button @click="visible2" type="success">fetch</el-button>
<br>
<el-progress v-if="this.percentage != 100" type="circle" :percentage="percentage"></el-progress>
<el-progress v-else type="circle" :percentage="100" status="success"></el-progress>
</div>
</body>
<script src="./js/vue2.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
new Vue({
el: '#app',
data: function () {
return { percentage: 0 }
},
methods: {
visible1: function () {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:3000/test');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = xhr.responseText;
}
}
xhr.addEventListener('progress', e => {
const { loaded, total } = e;
// console.log(loaded, total);
console.log(parseInt((loaded / total) * 100, 0) + '%');
this.percentage = parseInt((loaded / total) * 100, 0)
})
xhr.send()
},
visible2: function () {
fetch('http://localhost:3000/test')
.then(async res => {
if (!res || !res.body) {
return
}
const contentLength = res.headers.get('content-length');
let total = contentLength ? parseInt(contentLength, 10) : 0;
let loaded = 0;
const reader = res.body.getReader();
while (1) {
const { done, value } = await reader.read()
if (done) {
break
}
loaded += value.length
this.percentage = parseInt((loaded / total) * 100, 0);
console.log(parseInt((loaded / total) * 100, 0));
}
})
}
}
})
</script>
</html>
通过以上代码就可以实现文章开头gif里面的效果。再调试过程中,打开浏览器F12,网络内改为慢速3G,刷新时,右击刷新按钮,选择清空缓存硬刷新,要不然有缓存,后面在测试就会响应很快,看不出来效果。
在控制台打印百分比就会看到:
标签:百分比,const,xhr,res,响应,进度,loaded,total,fetch From: https://blog.csdn.net/m0_74213811/article/details/140180614