Skip to content

Latest commit

 

History

History
92 lines (70 loc) · 2.42 KB

17.md

File metadata and controls

92 lines (70 loc) · 2.42 KB

Javascript Debounce and Throttle

再處理網頁互動時,常常會有需要處理事件,有些事件會被呼叫的太頻繁而導致效能低落。例如 onScroll callback,就會被常常呼叫到在做重新 render 的動作。

簡單的解法可以設定計算量大的事件函數每 250 ms 執行一次。而目前已有眾多可行的解法處理這個問題,較常見的解法有 throttling 和 debouncing 等等。


範例

Debounce 和 throttle 的視覺化範例 http://demo.nimius.net/debounce_throttle/


Debounce 去抖動

讓一個函式在連續觸發時只執行一次

常見的用法是使用者連續輸入基本資訊後,才觸發事件處理器進行格式確認。

const debounce = (func, delay) => {
  let timer = null;
  return function () {
    let context = this;
    let args = arguments;
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(context, args)
    }, delay);
  }
}

const handleScroll = () => {
  console.log(window.scrollY)
}

window.addEventListener(‘scroll’, debounce(handleScroll));

程式碼很直觀,先設一個計時器 (timer),保存當下脈絡後 (context, args),只要太早進來 (小於 delay) 就會重置計時器,直到成功執行 setTimeout 內的函式後結束。


Throttle 函數節流

讓一個函數不要執行得太頻繁

減少一些過快的呼叫來節流。一個常見的用法是減少 scroll 的觸發頻率,因為 scroll 常常綁定一些消耗資源的 render 的事件。

const throttle = (func, threshhold) => {
  let last;
  let timer;
  if (threshhold) {
      threshhold = 250;
  }
  return () => {
    let context = this
    let args = arguments
    let now = +new Date()
    if (last && now < last + threshhold) {
      clearTimeout(timer)
      timer = setTimeout(() => {
        last = now
        func.apply(context, args)
      }, threshhold)
    } else {
      last = now
      fn.apply(context, args)
    }
  }
}

const handleScroll = () => {
  console.log(window.scrollY)
}

window.addEventListener(‘scroll’, debounce(handleScroll));

與 debouncing 的程式邏輯相似,只多了一個時間間隔的判斷。

Lodash

說了那麼多,目前 lodash 都有提供 debounce 與 throttle 的 function 可以使用,那真是太好了。


Reference

  1. https://mropengate.blogspot.com/2017/12/dom-debounce-throttle.html
tags: Javascript debounce throttle