promise.all 与 多个await 的区别

2024-04-28 10:27:51 浏览数 (1)

之前写一篇关于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;
  }

要了解为什么,我们需要知道以下几个问题的答案

  1. vue3中,响应式数据的修改是如何进行重新渲染的
  2. Promise.all 的原理
  3. 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会刷新多次

0 人点赞