JS限流與防抖


限流

在JS中,如果一個事件頻繁觸發(比如用戶瘋狂點擊按鈕)並且處理函數處理耗時還比較長,那么就容易造成性能問題。

限流函數是針對這類問題的優化方式之一,它要求兩次事件處理必須大於某個間隔時間,簡而言之就是加了一層判斷。

限流函數(throttle:節流閥)的核心在於內部維護了一個“上次執行時間點”,通過比較當前執行時間與上次執行時間的差值判斷是否“頻繁”,是否執行。限流函數本身是一個裝飾函數,修飾了事件處理器之后返回一個新的閉包函數。經過限流函數處理之后,事件觸發的頻率就被限制為預先傳入的interval之上了。

下面用代碼實現一個限流函數:

function throttle(fn, interval) {
  // 維護上次執行的時間
  let last = 0;

  return function () {
    const context = this;
    const args = arguments;
    const now = Date.now();
    // 根據當前時間和上次執行時間的差值判斷是否頻繁
    if (now - last >= interval) {
      last = now;
      fn.apply(context, args);
    }
  };
}

使用限流函數:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <button>click me</button>
    <script src="./throttle.js"></script>
    <script>
      const button = document.querySelector("button");
      button.addEventListener(
        "click",
        // 使用限流函數修飾事件處理器
        throttle((event) => {
          console.log("button click");
        }, 2000)
      );
    </script>
  </body>
</html>

防抖

防抖函數也是一種限流函數,但要特殊一些。最典型的場景是表單輸入,如果我們要在表單中監聽input事件(比如遠程搜索),那用戶在輸入的時候也會頻繁觸發,但這里使用throttle函數不行,因為我們需要等待用戶停止輸入一段時間后才能確認用戶輸入的值,所以要定義一個新的限流函數,叫做防抖函數。

防抖(防反跳)函數的核心是內部使用定時器並維護定時器返回的ID值,如果持續觸發則不斷clearTimeout()並重新發起setTimeout(),通過這種方式等待事件觸發完畢,然后進行延時處理。

下面用代碼實現一個防抖函數:

function debounce(fn, delay) {
  // 記錄定時器返回的ID
  let timer = null;

  return function () {
    const context = this;
    const args = arguments;
    // 當有事件觸發時清除上一個定時任務
    if (timer) {
      clearTimeout(timer);
    }
    // 重新發起一個定時任務
    timer = setTimeout(() => {
      fn.apply(context, args);
    }, delay);
  };
}

使用防抖函數:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <input type="text" />
    <script src="debounce.js"></script>
    <script>
      const input = document.querySelector("input");
      input.addEventListener(
        "input",
        debounce((event) => {
          console.log("input finish");
        }, 2000)
      );
    </script>
  </body>
</html>

這些常用的函數可以參考lodash庫

總結

限流函數和防抖函數都是為了應對“事件處理的速度跟不上事件觸發的速度”這樣的場景而產生的優化函數。

限流(throttle)要求兩次事件處理之間必須有一個間隔時間,防抖(debounce)要求最后一個事件觸發完畢后再執行。


免責聲明!

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



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