setTimeout/setInterval精確問題詳解及替代方案requestAnimationFrame


setTimeout/setInterval

Javascript定時器setTimeout/setInterval有一個非常明顯的問題是時間並不精確,參考下例:
假設有以下場景

setTimeout(function timeoutHandler(){
   /*Some timeout handle code that runs for 6ms*/
  }, 10);
  setInterval(function intervalHandler(){
   /*Some interval handle code that runs for 8ms*/
  }, 10);
  const myButton = document.getElementById("myButton");
  myButton.addEventListener("click", function clickHandler(){
   /*Some click handle code that runs for 10ms*/
  }); 

注冊延遲執行計時器,延遲10ms。
延遲執行回調函數需要執行6ms。
接着注冊一個間隔執行計時器,每隔10ms執行一次。
間隔執行回調函數需要執行8ms。
繼續注冊一個單擊事件處理器,需要執行10ms。
本例中的代碼塊需要運行18ms。
現在,假設某毫無耐心的用戶在程序執行6ms時快速單擊按鈕。

執行情況:
1、[0ms]執行主線程
2、[6ms]添加點擊事件到隊列中
3、[10ms]兩個計時器按照注冊順序加入宏任務隊列
4、[18ms]單擊和兩個計時器等待觸發,單擊開始執行
5、[20ms]間隔計時器又一次觸發,但是已經有該實例。觸發被終止。
6、[28ms]單擊事件執行完畢,執行延遲計時器任務。
7、[30ms]間隔計時器又一次觸發,但是已經有該實例。觸發被終止。
8、[34ms]延遲計時器執行完畢,執行間隔計時器任務。
9、[40ms]間隔計時器又一次觸發,間隔處理器正在執行,所以這次可以添加到任務隊列。
10、[42ms]間隔計時器執行完畢,執行剛剛添加的間隔計時器。
11、[50ms]間隔計時器執行完畢.間隔計時器又一次觸發。添加到任務隊列,此后10、11反復執行。

可以看到,定時器並未像預期執行。是因為JavaScript中定時器機制導致。由此引出替代方案requestAnimationFrame。須注意的是,requestAnimationFrame也屬於宏任務。

requestAnimationFrame

編輯中。。。
參考文獻:
《Secrets of the JavaScript Ninja》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM