之前写一篇关于vue请求太多,页面会多次进行刷新,最后使用了Promise.all 解决了这个问题,但一直没有理解为什么用多个await不能实现。具体可以参考之前的文章《vue 请求太多时的优化方法》
请看相关代码:
Promise.all的使用:使用后页面只刷新1次
(原理:使用Promise.all方法,先要将所有的请求变成Promise对象,再作为数组参数,供all方法使用)
代码如下:
代码语言:javascript复制const commonPromise= (funName:Function) =>{
return new Promise((resolve,reject)=>{
funName().then((res:any)=>{
resolve(res);
}).catch((err:any)=>{
reject(err);
})
})
}
const getDataInit2 = ()=>{
Promise.all([
commonPromise(getListCounselors),
commonPromise(getMajorListAll),
commonPromise(getClassAll),
commonPromise(getEnterResource),
commonPromise(getListBusiness)]).then((res)=>{
let [CounselorsResult,
MajorResult,
ClassResult,
resourceResult,
BusinessResult
]:any = res;
if(CounselorsResult.data.code==0){
data.value.CounselorsList = CounselorsResult.data.data;
}
//获取咨询课程,即所有方向
if(MajorResult.data.code==0){
data.value.MajorList = MajorResult.data.data;
}
if(ClassResult.data.code == 0){
data.value.ClassAll = ClassResult.data.data;
}
//获取录入资源信息
if(resourceResult.data.code == 0){
data.value.userList = resourceResult.data.data;
}
//业务划分
if(BusinessResult.data.code == 0){
data.value.ListBusiness = BusinessResult.data.data;
}
}).catch((err)=>{
ElMessage.error(err);
console.log("err");
console.log(err);
});
}
多个await的使用:使用后,页面还是刷新多次
代码如下:
代码语言:javascript复制
const getDataInit= async ()=>{
let CounselorsResult = await getListCounselors();
let MajorResult = await getMajorListAll();
let ClassResult = await getClassAll();
let resourceResult = await getEnterResource();
let BusinessResult = await getListBusiness();
if(MajorResult.data.code==0){
data.value.MajorList = MajorResult.data.data;
}
if(ClassResult.data.code == 0){
data.value.ClassAll = ClassResult.data.data;
}
if(resourceResult.data.code == 0){
data.value.userList = resourceResult.data.data;
}
if(CounselorsResult.data.code==0){
data.value.CounselorsList = CounselorsResult.data.data;
}
if(BusinessResult.data.code == 0){
data.value.ListBusiness = BusinessResult.data.data;
}
}
疑问:Promise.all 与 多个await 都实现了:先去获取所有的数据,再使用多个if进行判断,更新响应式数据。那为什么Promise.all就只刷新一次,而多个await却是有几个就刷新几次呢,所以,对它进行了一个研究,然后和大家一起分享一下
代码语言:javascript复制if(MajorResult.data.code==0){
data.value.MajorList = MajorResult.data.data;
}
if(ClassResult.data.code == 0){
data.value.ClassAll = ClassResult.data.data;
}
if(resourceResult.data.code == 0){
data.value.userList = resourceResult.data.data;
}
if(CounselorsResult.data.code==0){
data.value.CounselorsList = CounselorsResult.data.data;
}
if(BusinessResult.data.code == 0){
data.value.ListBusiness = BusinessResult.data.data;
}
要了解为什么,我们需要知道以下几个问题的答案
- vue3中,响应式数据的修改是如何进行重新渲染的
- Promise.all 的原理
- await 关键字的原理
问题1:vue3中,响应式数据的修改是如何进行重新渲染的
同一个Tick中多次更新数据,页面也只会更新一次
(所以,可以看出问题的重点在于,是否在同一个Tick中)
问题2:Promise.all 的原理
注意看代码:整个方法看成一个Promise对象,当数组promise对象全部resolve后,才返回resolve.
核心(关键):if (count === promises.length) resolve(arr)
代码语言:javascript复制Promise.MyAll = function (promises) {
let arr = [],
count = 0
return new Promise((resolve, reject) => {
promises.forEach((item, i) => {
Promise.resolve(item).then(res => {
arr[i] = res
count = 1
if (count === promises.length) resolve(arr)
}, reject)
})
})
}
问题3:await 关键字的原理
await 对执行过程的影响 当函数执行到 await 时,被等待的表达式会立即执行,所有依赖该表达式的值的代码会被暂停,并推送进微任务队列(microtask queue)。然后主线程被释放出来,用于事件循环中的下一个任务。 mdn
总结
Promise.all执行相当于在同一个Tick中; 而多个await, 一个await就相当于一个Tick,多个await就是多个Tick;
故:Promise.all只刷新一个,多个await会刷新多次