放棄setInterval-說說定時器

上述事件循環機制的核心是:JS引擎線程和事件觸發線程前端

但事件上,裏面還有一些隱藏細節,譬如調用setTimeout後,是如何等待特定時間後才添加到事件隊列中的?web

是JS引擎檢測的麼?固然不是了。它是由定時器線程控制(由於JS引擎本身都忙不過來,根本無暇分身)瀏覽器

爲何要單獨的定時器線程?由於JavaScript引擎是單線程的, 若是處於阻塞線程狀態就會影響記計時的準確,所以頗有必要單獨開一個線程用來計時。函數

何時會用到定時器線程?當使用setTimeoutsetInterval,它須要定時器線程計時,計時完成後就會將特定的事件推入事件隊列中。學習

 

  • 即使是0毫秒後就推入事件隊列,可是W3C在HTML標準中規定,規定要求setTimeout中低於4ms的時間間隔算爲4ms。(不過也有一說是不一樣瀏覽器有不一樣的最小時間設定)優化

  • 就算不等待4ms,就算假設0毫秒就推入事件隊列,時間也不必定準確。由於只有可執行棧內空了後纔會主動讀取事件隊列。spa

那是用setTimeout仍是setInterval?

 

用setTimeout模擬按期計時和直接用setInterval是有區別的。線程

由於每次setTimeout計時到後就會去執行,而後執行完內部代碼後,因此這裏可能有一段時間後纔會繼續setTimeout,中間就多了偏差(偏差多少與代碼執行時間有關)code

而setInterval則是每次都精確的隔一段時間推入一個事件(可是,事件的實際執行時間不必定就準確,還有多是這個事件還沒執行完畢,下一個事件就來了)隊列

並且setInterval有一些比較致命的問題就是:

  • 累計效應(上面提到的),上一個還沒執行完。

就會致使定時器代碼連續運行好幾回,而之間沒有間隔。
就算正常間隔執行,多個setInterval的代碼執行時間可能會比預期小(由於代碼執行須要必定時間)

  • 譬如像iOS的webview,或者Safari等瀏覽器中都有一個特色,在滾動的時候是不執行JS的,若是使用了setInterval,會發如今滾動結束後會執行屢次因爲滾動不執行JS積攢回調,若是回調執行時間過長,就會很是容器形成卡頓問題和一些不可知的錯誤(聽說setInterval自帶優化,不會重複添加回調)

  • 並且把瀏覽器最小化顯示等操做時,setInterval並非不執行程序,

它會把setInterval的回調函數放在隊列中,等瀏覽器窗口再次打開時,一瞬間所有執行時

因此,鑑於這麼多但問題,目前通常認爲的最佳方案是:用setTimeout模擬setInterval,或者特殊場合直接用requestAnimationFrame

補充:JS高程中有提到,JS引擎會對setInterval進行優化,若是當前事件隊列中有setInterval的回調,不會重複添加。不過,仍然是有不少問題。。。

 

最後留一個做業 setInterval 會不會累計,驗證他的執行特色。

 

到這裏我們這個系列快說完了,還有最後一節,如今不知道你們聽了這些後有什麼感想,不知道對你們有麼有幫助。我自認爲啊有些地方說的不夠明確和透徹。不少都是把點帶出來了,有些細節可能還須要你們繼續學習,查一些資料進行深刻研究或者關注下重度前端這個號 我本身的號,分享的內容都有文字版的,也包括我平常工做中的一些技術總結和積累。今天太晚了,最後一節我先想一想怎麼說吧。

 

再見,各位。

相關文章
相關標籤/搜索