N多年前,leader讓作一個網頁,給了一個設計png,content部分分好幾塊,而後這幾塊內容裏面的數據不停的來回切換,當時第一反應就是setInterval 循環播放,一個網頁大概半天時間就作好了,成品跟設計png幾乎如出一轍,很滿意,打包發給了leader。
然而,過了幾天,leader說你作的網頁爲何過了會,點什麼都沒反應,你去看看怎麼回事。當時就以爲奇怪,我本地運行的好好的,沒有任何異常,也沒他說的卡死啊,而後就網上各類搜索,看看問題到底出在哪裏。後來只記得當時的產物是
`window.setInterval(() => {
vue
setTimeout(fun, 0)
服務器
}, 30000)
`網絡
並不知道爲何要這樣作,只知道這樣寫了之後,網頁不會再卡死。當時也沒有去研究到底爲何。依稀記得當時也網上搜索了,沒有找到答案。性能
後面工做不少年,只要使用到循環就一直按照這種寫法,沒有遇到過卡死的問題,有次聽公開課的時候,問了下老師,爲何要這樣寫,老師只說這樣寫性能好,並無說爲何。測試
今天恰好看同事代碼,告訴她循環不建議那麼寫,我給你找個比較好的寫法,我本身也說不上來爲何要這樣寫,既然疑惑這麼多年,今天恰好有空,我來查查爲何。this
網上的說明 setinterval不會清除定時器隊列,每重複執行1次都會致使定時器疊加,最終卡死你的網頁
其緣由與JS引擎線程有關(又得研究下JS引擎線程了) 可是setTimeout是自帶清除定時器的.net
參考 https://blog.csdn.net/helenwe...線程
另外搜索到一些弊端
弊端1:setInterval會無視錯誤代碼,即便代碼報錯,仍是會一直執行下去。設計
弊端2:setInterval會無視網絡延遲,不少人會有需求須要1秒更新一次數據,而後就有可能會定時發送請求給服務器請求,假如服務器請求數據發生延遲等等狀況的時候,setInterval不會等到請求數據完以後纔去去執行下一次請求,他會在當你發生第一次請求的時候就已經開始計時,而且不管有沒有請求完成,只有時間一到下一秒的時候,就會再次發送請求。很容形成請求堵塞,或者渲染堵塞,嚴重的會之間卡死。code
注: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)
}`