项目背景
帮同学课设做实时数据展示,同学后端数据是检测实时的充电桩电流,电压等参数,然后以折线图和表格的形式实时展示到前端界面,因为他没有用websocket的连接方式给我数据,所以我要用比较落后原始的每隔一定时间发起一个请求的方式做到实时展示数据
项目展示
github地址:这里!这里!
入坑
一般做实时数据请求不采用websocket的话,而使用轮询的请求有两种方式,即:
setInterval(function(){方法}, 2000)
这种方法是每过两秒就自动创建一个异步操作请求数据,不管是DOM渲染延迟还是网络堵塞,都会持续每隔2秒时间去请求,颇有种“我只管定时请求,哪管它洪水滔天”的味道,所以这个坑我一开始就放弃了
setTimeout(function(){方法}, 2000)
这种方法是方法里面设置一个定时器,2秒后执行,然后继续在定时器里面继续执行本身,有点递归的味道,不过只有传递,没有回归的递归,因为考虑到dom重新渲染和网络延迟的问题,我就用了这个方法
踩坑
当我用setTimeout(function(){方法}, 2000)
方法后,我发现刚开始还是好的,折线图每隔2S数据自动刷新一次,后面我再切换充电桩的时候它就会数据刷新变快,多次点击后就变成了折线图会一秒刷新好几次
后来我在devtools中寻找原因的时候,发现当我切换充电桩后,就会多开启一个请求:简单来讲就是我点击“充电桩1”,他是会每隔2秒发起对一个充电桩1的数据请求,然后我点击“充电桩2”,他每隔2秒发起两个对充电桩2的数据请求,我再点击回“充电桩1”,他就每隔2秒发起三个对充电桩1的数据请求,再点再加……
请求对象是对的,但是点击一次会多一个网络请求,后面也就造成了数据刷新很快,如果2秒请求4次就相当于0.5秒刷新一次
填坑
这里出现了一种假象,也就是我每点击一次,好像就增加了一个线程,然后共同执行请求,但是JavaScript是单线程的
axios请求和ajax一样都是异步执行,也就是在主线程同步任务执行完毕后执行axios内部的回调函数,setTimeout()
的方法也是异步执行的,所以又进入等待队列,axios内部执行完后再从异步任务队列中执行setTimeout()
的函数,然后我每次切换充电桩的时候,产生一次点击事件,setTimeout()
内部又独立出了一个setTimeout()
,再点击再出现一个,跟细胞分裂一样
出坑
emmmm……
其实解决方案很简单:
在vue的data中设置一个标志位
let id=setTimeout();
this.timeTag = a;
然后在方法开头
clearTimeout(this.timeTag);
咳咳……就是这么简单