[JS] Debounce

以文字輸入框為例,連續輸入時,不會觸發動作(比如:查詢資料庫),要停止輸入並等待一段時間後才觸發動作。

下面的程式會在每次輸入時,清除前一個 setTimeout 並設置一個新的 setTimeout,直到停止輸入,並等待設定的秒數(這個例子是一秒)後觸發動作。

簡單的版本:

let timer;

inputText.addEventListener('input', (e) => {
  clearTimeout(timer);

  timer = setTimeout(() => {
    showArea.textContent = e.target.value; // 要觸發的動作
  }, 1000);
});

Demo
https://www.yuantw.com/demo/js-debounce-1/

———

網路上的資料都是把 debounce 寫成函式:

inputText.addEventListener('input', debounce(showData));

function debounce(fn, delay = 1000) {
  let timer;

  // return 的 function 是 inputText.addEventListener 的 event handler
  return (e) => {
    clearTimeout(timer);

    timer = setTimeout(() => {
      fn(e);
    }, delay);
  };
}

function showData(e) {
  showInfo.textContent = e.target.value;
}

Demo
https://www.yuantw.com/demo/js-debounce-2/

———

上面二個例子的行為是,事件連續發生,停止後,只觸發動作一次。

debounce 也可以實作成,立即觸發動作

簡單的版本:

let timeoutID;

btn.addEventListener('click', () => {
  if (!timeoutID) {
    console.log(new Date());
  }

  clearTimeout(timeoutID);

  timeoutID = setTimeout(() => {
    timeoutID = null; // reset
  }, 1000);
});

Demo
https://www.yuantw.com/demo/js-debounce-now-1/

———

下面的程式碼是從 JavaScript30 13 – Slide in on Scroll 修改

function debounce(func, wait = 1000, immediate = true) {
  let timeoutID;

  return (e) => {
    if (immediate && !timeoutID) {
      func(e);
    }

    clearTimeout(timeoutID);

    timeoutID = setTimeout(() => {
      timeoutID = null; // reset

      if (!immediate) {
        func(e);
      }
    }, wait);
  };
}

Demo
https://www.yuantw.com/demo/js-debounce-now-2/


參考連結:

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

返回頂端