為什麼 setInterval 在使用上時間會不太準

Why

  1. JS 的 event loop 以及單執行緒機制,導致需要先將 callback 放進 callback queue 裡

  2. 等到 call stack 清空時才會將 callback 從 callback queue 推入 call stack

  3. setInterval 會過每固定時間就把 callback 放進 callback queue, 但先前的任務可能還沒執行完,當 callback 需要花較久時間做執行時,就會導致 callback queue 裡面有多個 callback,當前面的 callback 一結束時就會馬上執行下一個 callback,如此一來也做不到間隔的效果

How

使用 setTimeout 代替 setInterval 

let lastCall = Date.now();
function intervalCall() {
  let now = Date.now();
  let delay = now - lastCall;
  lastCall = now;
  console.log("interval---", delay);
  setTimeout(intervalCall, 2000);
}
intervalCall();
 

image 38.png

使用 requestAnimationFrame

利用 requestAnimationFrame 讓回調在瀏覽器重繪前執行,適合動畫等場景。

let lastCall = Date.now();
function intervalCall() {
  let now = Date.now();
  let delay = now - lastCall;
  if (delay >= 2000) {
    console.log("interval---", delay);
    lastCall = now;
  }
  requestAnimationFrame(intervalCall);
}
requestAnimationFrame(intervalCall);
 

image 39.png

另外還有

  • web worker

  • setTimer 的補償

  • setInterval 的補償