返回課程

Debounce 裝飾器

重要性:5

debounce(f, ms) 裝飾器的結果是一個包裝函式,它會暫停對 f 的呼叫,直到 ms 毫秒的非活動時間(沒有呼叫、「冷卻時間」),然後使用最新的引數呼叫 f 一次。

換句話說,debounce 就像一位秘書,負責接「電話」,並等待安靜的毫秒數達到 ms。然後才會將最新的通話資訊轉達給「老闆」(呼叫實際的 f)。

例如,我們有一個函式 f,並將其替換為 f = debounce(f, 1000)

然後,如果在 0 毫秒、200 毫秒和 500 毫秒呼叫包裝函式,接著沒有呼叫,則實際的 f 將只會在 1500 毫秒時呼叫一次。也就是說:在最後一次呼叫的冷卻時間 1000 毫秒後。

…而且它會取得最後一次呼叫的引數,其他呼叫都會被忽略。

以下是其程式碼(使用 Lodash 函式庫 中的 debounce 裝飾器)

let f = _.debounce(alert, 1000);

f("a");
setTimeout( () => f("b"), 200);
setTimeout( () => f("c"), 500);
// debounced function waits 1000ms after the last call and then runs: alert("c")

現在舉一個實際的例子。假設使用者輸入一些內容,我們希望在輸入完成時向伺服器發送請求。

沒有必要在輸入每個字元時都發送請求。我們希望等待,然後處理整個結果。

在網路瀏覽器中,我們可以設定一個事件處理常式,也就是在輸入欄位每次變更時呼叫的函式。通常,事件處理常式會非常頻繁地呼叫,也就是在輸入每個按鍵時。但是,如果我們使用 1000 毫秒對其進行 debounce,則它只會在最後一次輸入後 1000 毫秒呼叫一次。

在此範例中,處理常式會將結果放入下方的方塊中,請試試看

看到了嗎?第二個輸入呼叫了 debounced 函式,因此其內容在最後一次輸入後 1000 毫秒才處理。

因此,debounce 是處理一系列事件的絕佳方法:無論是按鍵序列、滑鼠移動或其他事件。

它會在最後一次呼叫後等待指定的時間,然後執行其函式,該函式可以處理結果。

任務是實作 debounce 裝飾器。

提示:如果你仔細想想,這只有幾行而已 :)

開啟具有測試的沙盒。

function debounce(func, ms) {
  let timeout;
  return function() {
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, arguments), ms);
  };
}

呼叫 debounce 會傳回一個包裝器。呼叫時,它會在指定的 ms 後排程原始函式呼叫,並取消前一個此類逾時。

在沙盒中開啟具有測試的解決方案。