1
使用场景

N多年前,leader让做一个网页,给了一个设计png,content部分分好几块,然后这几块内容里面的数据不停的来回切换,当时第一反应就是setInterval 循环播放,一个网页大概半天时间就做好了,成品跟设计png几乎一模一样,很满意,打包发给了leader。
然而,过了几天,leader说你做的网页为什么过了会,点什么都没反应,你去看看怎么回事。当时就觉得奇怪,我本地运行的好好的,没有任何异常,也没他说的卡死啊,然后就网上各种搜索,看看问题到底出在哪里。后来只记得当时的产物是
`window.setInterval(() => {

setTimeout(fun, 0)

}, 30000)`

并不知道为什么要这样做,只知道这样写了以后,网页不会再卡死。当时也没有去研究到底为什么。依稀记得当时也网上搜索了,没有找到答案。

后续

后面工作很多年,只要使用到循环就一直按照这种写法,没有遇到过卡死的问题,有次听公开课的时候,问了下老师,为什么要这样写,老师只说这样写性能好,并没有说为什么。

今天刚好看同事代码,告诉她循环不建议那么写,我给你找个比较好的写法,我自己也说不上来为什么要这样写,既然疑惑这么多年,今天刚好有空,我来查查为什么。

网上的说明 setinterval不会清除定时器队列,每重复执行1次都会导致定时器叠加,最终卡死你的网页
其原因与JS引擎线程有关(又得研究下JS引擎线程了) 但是setTimeout是自带清除定时器的

参考 https://blog.csdn.net/helenwe...

另外搜索到一些弊端
弊端1:setInterval会无视错误代码,即使代码报错,还是会一直执行下去。

弊端2:setInterval会无视网络延迟,很多人会有需求需要1秒更新一次数据,然后就有可能会定时发送请求给服务器请求,假如服务器请求数据发生延迟等等情况的时候,setInterval不会等到请求数据完之后才去去执行下一次请求,他会在当你发生第一次请求的时候就已经开始计时,并且无论有没有请求完成,只有时间一到下一秒的时候,就会再次发送请求。很容造成请求堵塞,或者渲染堵塞,严重的会之间卡死。

注:vue 项目的时候,如果页面使用到循环定时器,调用后台接口出现异常,在切换路由地时候并不能清除定时器。(目前我测试出来,是这样的)
` beforeRouteLeave(to, from, next) {

console.log('beforeRouteLeave')
this.clearTimer()
next() //一定不要忘记写

}`

弊端3:很多时候越跑越快的问题。

解决方案:使用setTimeout和递归(自我调用)

例如:

使用 setInterval 方案(不推荐使用)

`setInterval(function(){

console.log('做点什么吧')

},1000)`
使用 setTimeout 方案 (推荐使用,完美代替setInterval) 注:有待验证

`var demo = function(){

console.log('做点什么吧')
setTimeout(demo, 1000)       

}`


tina666
392 声望7 粉丝

别回头,别人随时有可能赶上你