vue中一个页面引入多个相同组件重复请求的问题?

⚠️!!!此内容需要了解一下内容!!!

1、会使用promise???

2、 promise跟 async 的区别???

async 会终止后面的执行,后续代码都需要等待 await 接收以后再执行,暂停页面执行顺序

promise不会,只要微任务结束,就会执行同步任务

3、宏任务,微任务执行顺序。???

如下图,页面调用同一个组件N次,如何进行优化

解决方案1.1:接口返回的 promise 状态进行缓存

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>02多请求cache-then</title>
</head>
<body>
  <script>
    let cache = null;

    function getData() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log('进入请求接口')
          // resolve({msg: '请求成功', data: [1,2,3,4]})
          reject({msg: '请求失败'})
        }, 100)
      })
    }

    async function initialRequest(msg) {
      console.log(msg)
        if (cache) { return cache; }
   
        if(!cache) {
            // 是第 1 个就去请求
            // (这个示例代码没做容错,自己加)
            try {
              cache = await getData()
               /*
                  不使用await
                  cache = getData()
                  缺点:请求失败的不好处理,每一个调用initialRequest函数,都需要.catch,代码冗余
                
                  使用 await
                  cache = await getData()
                  代码逻辑错误:每一次 initialRequest 函数都会执行,都会产生自己的 getData 函数
                */
            } catch(error) {
              cache = null
              initialRequest('报错请求')
            }
        }
        console.log('使用async,if判断之外的也不会执行')
        return cache;
    }
debugger
    initialRequest('第一请求').then((res) => {
      console.log('一请求--res', res)
    })
    initialRequest('第二请求').then((res) => {
      console.log('二请求--res', res)
    })
    
  </script>
</body>
</html>

有缺陷,在initialRequest函数中

复制代码
1、不使用await
cache = getData()
缺点:请求失败的不好处理,每一个调用initialRequest函数,都需要.catch,代码冗余
                
 2、使用 await
 cache = await getData()
代码逻辑错误:每一次 initialRequest 函数都会执行,都会产生自己的 getData 函数

方案1.2:增加睡眠函数,配合async await 完美使用

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>02多请求cache-async</title>
</head>
<body>

  <script>
   
    let cache = null;
    let count = 0;
    let flag = false

    function getData() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log('进入请求接口')
          if (!flag) {
            reject({msg: '请求失败'})
            flag = true
          } else {
            resolve({msg: '请求成功', data: [1,2,3,4]})
          }
        }, 100)
      })
    }

    async function delay(ms = 200) {
      return new Promise(resolve => {
        console.log('进入睡眠函数')
        setTimeout(resolve, ms) // 200 毫秒以后执行这个promise
      });
    }

    async function initialRequest(msg) {
      console.log(msg)
        if (cache) { return cache; }

        if (count++) {
            // 如果有计数说明自己不是第 1 个,就等。注意这里判断的是加之前的 count
            // 循环里最好再加个超时判断
            while (!cache) { 
              const abc = await delay();
              console.log('await会阻止向下循环', abc)
            } // 睡眠是什么意思
        } else {
            try {
              cache = await getData();
            } catch(error) {
              // 判断如果第一个接口请求失败,重新发起请求,直到成功
              count--
              cache = await getData();
              // cache = error
            }
            /*
              使用这个的好处,是从第二次的delay执行完之后都会获取到第一次 getData 执行的结果,
              不用每个函数都添加catch监听错误信息,也可以在try catch中做兼容处理,加入请求失败了,再次发起请求
            */
        }
        console.log('使用async,if判断之外的也不会执行')

        count--;    // 记得减回去,方便以后如果要刷新 cache 的时候用
        return cache;
    }
debugger
    initialRequest('第一请求').then((res) => {
      console.log('一请求--res', res)
    })
    initialRequest('第二请求').then((res) => {
      console.log('二请求--res', res)
    })
    initialRequest('第三请求').then((res) => {
      console.log('三请求--res', res)
    })
   /*  */
  </script>
</body>
</html>

好处:1、如果第一个请求接口异常,可捕获错误,重新发起请求,不影响后面睡眠的函数,最终只需要接收 cache 就行。

2、不用每个函数都添加catch监听错误信息,也可以在try catch中做兼容处理,请求失败了,可再次发起请求(看try catch部分)

那么要做什么文章呢?我们假设这个页面引入多个相同的组件,都是调用同一个 initailRequest 方法。那么在这个方法外部添加一个缓存 cache,组件每次先从这个缓存对象查找存不存在配置数据。如果存在直接获取缓存对象,如果不存在就调用接口获取。但光是这样效果还是和方案1.0结果一样的,同样会调用30次接口。所以我们还需要加一个计数器变量 count。count 的初始值是0,initailRequest 组件每次发送请求时都会给 count 加1。这样子当我们发现是第一次请求时就去调用接口,不是第一次的话就等待,直到第一次请求结束获得数据。逻辑流程图如下:

参考链接:
从解决一个页面请求太多的问题开始的
promise/ async await 的区别

相关推荐
牛蛙点点申请出战11 分钟前
IconFontViewer -- 一个可以在 Android Studio 中实时预览 IconFont 的插件
android·前端·intellij idea
空中海13 分钟前
03 渲染机制、性能优化与现代 React
javascript·react.js·性能优化
ChalesXavier40 分钟前
Fetch API 的基本用法
javascript
是上好佳佳佳呀1 小时前
【前端(十三)】JavaScript 数组与字符串笔记
前端·javascript·笔记
巴沟旮旯儿1 小时前
vite项目配置文件和打包
前端·设计模式
彩票管理中心秘书长1 小时前
Pinia 插件架构与组合式函数:如何让你的 Store 长出“超能力”
前端
彩票管理中心秘书长1 小时前
Pinia 比 Vuex 强在哪?我用同一个模块写了两种实现,你自己看
前端
yingyima1 小时前
用 Cron 加 Webhook 打通自动化工作的任督二脉
前端
JackieDYH1 小时前
CSS Flexbox 与 Grid 的默认行为-布局的底层机制
前端·css·html
彩票管理中心秘书长1 小时前
E2E测试入门:别让用户帮你点鼠标了,找个机器人替你打工吧
前端