vue数据大屏并发请求

并发? 处理并发

因为js是单线程的,所以前端的并发指的是在极短时间内发送多个数据请求,比如说循环中发送 ajax , 轮询定时器中发送 ajax 请求. 然后还没有使用队列, 同时发送 的. 

1. Promise.all

可以采用Promise.all处理并发, 当所有promise全部成功时, 会走.then,并且可以拿到所有promise中传进resolve中的值

Promise.all([ WsApi.querySpyTaskSummary(), WsApi.querySpyTask(), ]).then((res) => { console.timeEnd(); });

注意: forEach 不能 await等待, map则可以, 结合promise完善代码

      this.upTrackCard(); // 先更新一次 card
      this.upFenceCard(); // 先更新一次 card

      // this.onDialogOpened(); // 测试--------- 更新

      // 定时器 timer 围栏
      if (this.timer) clearInterval(this.timer);
      this.timer = setInterval(() => {
        setTimeout(() => {
          this.upFenceCard(id); // 定时更新 card
        }, 0);
      }, 2000);

      // 定时器 timer 轨迹
      if (this.timerTrack) clearInterval(this.timerTrack);
      this.timerTrack = setInterval(() => {
        setTimeout(() => {
          this.upTrackCard(id); // 定时更新 轨迹
        }, 0);
      }, 2000);




// 更新轨迹
    async upTrackCard(id) 

      // 根据 mapId 查询地图上工具 tagIds
      let tagIds = [];
      await getToolsMapMapTags(id).then((response) => {
        // console.log("地图工具信息:", response);
        // 没有工具时候
        if (response.length === 0) {
          //
          console.log("没有===========工具===========");
          // this.openDetail = true; //打开弹框: 队列执行完了再打开弹框,要不然提前打开,代码却没有执行完, 造成空渲染
          // this.fullscreen = true; //弹框全屏
          // this.onDialogOpened(); // 测试--------- 更新
        }
        // 有工具的时候
        else if (response.length != 0) {
          //
          tagIds = response.map((item) => item.id);
        }
      });
      this.imageList = []; // 响应了再清空

      let tagList = {}; // 报警
      let tagIdsAll = tagIds.map(async (tagId) => {
        // 根据 tagId 获取工具 当前位置 图片地址
        await getToolsTracePosition(tagId).then((response) => {
          // console.log(response.remark, "remark=====================");
          // console.log("地图工具图片定位:", response);

          let imageObject = {
            tagLogoDir: response.tagLogoDir, // 工具图片地址
            tagMeterX: response.tagMeterX * this.circle_PxToM_X, // x
            tagMeterY: response.tagMeterY * this.circle_PxToM_Y, // y
          };
          this.imageList.push(imageObject);
      });
      try {
        await Promise.all(tagIdsAll);
      } catch (error) {
        console.log("Promise执行中抛出了错误, 也打开弹框");
        // this.openDetail = true;
      }
      // console.log(
      //   tagIdsAll,
      //   "Promise完成, 打开弹框---------------==============="
      // );
      await this.onDialogOpened(); // 测试--------- 更新
      //
    },

2. async/await (个人喜欢用这个)

  data() {
    return {
        timer: null, // 定时器名称 队列
        timerRefresh: null, // 定时器 2小时刷新页面 
    }
  },

  mounted() {
    this.startTimer() // 定时发送请求获取数据并更新对象 3s
    this.startTimerRefresh() // 定时刷新页面 2h 

    // this.startDayCap()// 日产能 3s
    // this.startMonthCap() // 月产能 5s
    // this.startOnlineTime()// 在线时长(小时) 10s
  },

  beforeDestroy() {
    // console.log('关闭定时器')
    if (this.timer) {
      clearInterval(this.timer)
      clearInterval(this.timerRefresh)

      // clearInterval(this.timerDayCap)
      // clearInterval(this.timerMonthCap)
      // clearInterval(this.timerOnlineTime)
    }
  },
  methods: {
    // #####################################################################
    // 定时器 队列
    startTimer() {
      this.fetchAll() // 开始请求一次

      if (this.timer) clearInterval(this.timer) // 清空上一个定时器
      // 开启定时器
      this.timer = setInterval(() => {
        this.fetchAll() // 机器人状态汇总

        // 优化释放异步资源方案未使用
        // setTimeout(() => {
        //   this.fetchAll() // 机器人状态汇总
        // }, 0)
      }, 3000)
    },
    //定时刷新页面
    startTimerRefresh() {
      if (this.timerRefresh) clearInterval(this.timerRefresh)
      this.timerRefresh = setInterval(() => {
        window.location.reload(true)
        // 刷新
        console.log("刷新");
      }, 2 * 60 * 60 * 1000) // 2 h
    },

    //
    //
    //
    async fetchAll() {
      // 日产能定时器
      await WeldHomeGetGroupDayCap().then(res => {
        // console.log(res, '日--------------');
        if (res.code === 200) {
          // 
          // this.props_productComponent_day = {}
          // 
          this.props_productComponent_day = {
            dataName: res.data.map(item => item.robotName),
            dataNum: res.data.map(item => item.realCap.toFixed(2) * 1)
          }
          // console.log(this.props_productComponent_day);
        } else {
          // this.msgError('err')
        }
      }).catch(err => {
      })
      // 月产能
      await WeldHomeGetGroupMonthCap().then(res => {
        // console.log(res, '月产能--------------');
        if (res.code === 200) {
          // 
          // this.props_productComponent_month = {}
          // 
          // const seriesData = day_xAxis_series_Data.map((item, index) => {
          //   return item.map(item => {
          //     return Number(item.rate)
          //   })
          // })

          this.props_productComponent_month = {
            robotNameList: res.data.map(item => item.robotName), // x轴
            seriesData: res.data.map(item => item.realCap.toFixed(2) * 1)  // y轴
          }
        } else {
          // this.msgError('err')
        }

      }).catch(err => {
      })
        
      // 放 try catch也可以的,因为有的会结合使用
      try {
         // let 变量1
         // let 变量2

         // await 1
         // await 2
      } catch (error) {
        // console.log(111);
      }
   }

每隔几秒请求一次接口(轮询)页面过段时间会卡死?

如果要求不高的话,最简单的就是 定时刷新, 如上边的2小时刷新方案.

当然,首先我们要排查是哪方面的错误, 后端接口的问题,还是前端代码执行顺序的问题,并发是否串行了. 等等......

eg: 某个页面放置一段时间(几分钟,几小时,几天),点不了,刷新页面也要很长时间才能响应或者不响应. 卡顿问题,只有关闭页面,重新打开才正常 ===>>> 浏览器内存堆满问题, 比较明显的,谷歌快照能看到 (performance快照、memory快照)

轮询定时器 清除 + vue2.0_vue监听缓存数据变化后清除定时器-优快云博客文章浏览阅读563次,点赞9次,收藏10次。轮询定时器 清除 + vue2.0_vue监听缓存数据变化后清除定时器https://blog.youkuaiyun.com/qq_60839348/article/details/135534331

单纯使用setInterval会使页面卡死,setTimeout自带清除缓存,组合使用实现轮询可解决浏览器崩溃 

这个setTimeout闭包也可以: 但是需要注意: demo 函数的执行时间超过定时器间隔,就会出现堆积的情况,导致性能下降甚至页面卡顿。滑动验证页面icon-default.png?t=N7T8https://segmentfault.com/a/1190000038886919

window.setInterval(() => {
  setTimeout(fun, 0)
}, 30000
<script>
export default {
 data() {
  return {
   num: 0,
   timer: null,
  };
 },
 destroyed() {
 //离开页面是销毁
    clearInterval(this.timer);
    this.timer = null;
 },
 created() {
      // 实现轮询
      this.timer = window.setInterval(() => {
        setTimeout(this.getProjectList(), 0); // 发送请求
      }, 3000);
 },
 methods: {
    stop() {
      clearInterval(this.timer);
      this.timer = null;
    },
    // 请求是否有新消息
    getProjectList() {
        console.log("请求" + this.num++ + "次");
        if(this.num==8){
        this.stop() 
    }
  }
 }
};
</script>

补充说明一下: 页面卡死也可能是dom堆积没有释放造成的!!! 

我最近做了个项目,konvajs绘制围栏,轨迹,工具的, 也是放在定时器中刷新的, 一般200个请求后就会内存爆了

谷歌快照可以看: 我看不懂, 就代码一步步排查了

排查1, 先后端整合接口, 单发请求,不做其他操作, 循环了2000次后,依旧不卡页面: 接口无问题

排查2, 执行js, 循环2000次后依旧咩问题

排查3, 加上konvajs绘制, 200次左右,页面卡死

结论: dom 的绘制一直是刷新的,看似替换,实则缓存了. 

          释放缓存, konvajs实例释放

代码优化: 只加载一次的, 只调用一次即可, 其他循环更新的,则加入到循环体中发请求更新

                 相同元素则做一次性处理: 比如批量圆, 图标

                也可以缓存池, 已经有的只要没变则不动

eg: 详情如下,弹框中的 konvajs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值