文章

前端面試手寫練習 - throttle

文章發表於

問題

throttle 是一個函式,它可以限制一個函式在一段時間內只能執行一次。當函式被調用時,它將會在 wait 毫秒後執行。如果在這段時間內函式再次被調用,將會被忽略。

可以把它想像成節流的概念,可以限制某些事件或是行為其被觸發的頻率。

throttle(func, [(wait = 0)])
  • func:要節流的事件函式
  • wait:延遲時間,單位為毫秒

示意圖

原始事件流 (每 ─ 代表 1s):
─ A ─ B ─ C ─ ─ D ─ ─ ─ ─ ─ ─ E ─ ─ F ─ G
加入 throttle (wait: 3s) 之後:
─ A ─ ─ ─ C ─ ─ ─ ─ ─ ─ ─ ─ ─ E ─ ─ ─ ─ G

可以看到加入 throttle 之後,函式 BF 被忽略了,而在忽略的那段時間就是冷卻時間。

範例

舉例來說,有時我們需要根據頁面的寬度來切換手機或桌機的 UI。這時可以透過 resize 事件來監聽視窗大小的變化,進而對 UI 進行改動。由於我們只需要知道頁面寬度是否達到臨界點,因此不需要在每一次 resize 事件觸發時都去執行改動。這時候就可以透過 throttle 來限制執行的頻率。

window.addEventListener('resize', throttle(onResize, 1000))

練習區

在了解問題後,可以嘗試先寫下您的思路,再到下方的練習區域實際寫出程式碼。

import { add } from './add';

describe('add', () => {
  test('Commutative Law of Addition', () => {
    expect(add(1, 2)).toBe(add(2, 1));
  });
});

Open browser consoleTests

筆者思路

  1. 由於這是一個節流函式,因此需要一個開關來控制是否可以執行。所以先建立一個變數 isThrottled 來控制是否可以執行。
  2. 接下來,當每次函式被調用時,需要確認是否可以執行。如果 isThrottledtrue,則直接返回。
  3. 如果可以執行,則將節流開關開啟 (isThrottled 設為 true),並通過 setTimeout 在 wait 毫秒後將開關關閉 (isThrottled 設為 false)。

筆者解答

function throttle(func, wait = 0) {
let isThrottled = false;
return function (...args) {
if (isThrottled) {
return;
}
isThrottled = true;
setTimeout(() => {
isThrottled = false;
}, wait);
func.apply(this, args);
};
}

相關題目

  1. throttle (進階)
  2. bigfrontend.dev - basic throttle

延伸閱讀

  1. Debounce vs Throttle: Definitive Visual Guide
如果您喜歡這篇文章,請點擊下方按鈕分享給更多人,這將是對筆者創作的最大支持和鼓勵。