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


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

    1、会使用promise???

    2、 promise跟 async 的区别???

    async 会终止后面的执行,后续代码都需要等待 await 接收以后再执行,暂停页面执行顺序
    promise不会,只要微任务结束,就会执行同步任务

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

    如下图,页面调用同一个组件N次,如何进行优化在这里插入图片描述

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

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>02多请求cache-thentitle>
    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    有缺陷,在initialRequest函数中

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

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

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>02多请求cache-asynctitle>
    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

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

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

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

    请添加图片描述

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

  • 相关阅读:
    字符串的认识
    Java的IO流-转换流
    Pytorch 实战 LESSON 5 基本优化方法与最小二乘法
    Java模拟电影院购票系统
    MongoDB
    前端性能测试工具WebPagetest
    安装konga
    信奥学习规划 信息学竞赛之路(2022.07.31)
    Android Fragment 基本概念和基本使用
    【云原生】使用Docker快速部署openGauss主备环境
  • 原文地址:https://blog.csdn.net/qq_43631129/article/details/134419476