什麼是節流 (throttle)?如何實踐節流 (throttle) 函式?
2022年12月11日
💎 加入 E+ 成長計畫 如果你喜歡我們的內容,歡迎加入 E+,獲得更多深入的軟體前後端內容
防抖 (debounce) 和節流 (throttle) 絕對是在考手寫題時最常出現的前幾名,這兩者都能做到優化,但使用情境不太相同,本篇介紹節流(throttle)函式,在這篇文章中會繼續討論防抖。
節流 (throttle) 在做什麼?
節流 (throttle) 指的是,在一段時間內只會執行一次觸發事件的回調 (callback) 函式,若在這之中又有新事件觸發,則不執行此回調函式。
在手寫節流 (throttle) 函式前,我們先來了解節流的使用情境。
監聽滾動事件,是搭配節流的使用場景之一。舉例來說,要判斷使用者是否已經滑動到頁面的 30% 處,當到達時會觸發一些動畫效果,因此,會透過監聽滾動事件時計算是否已到達該位置,但如果只要一滾動就計算會非常消耗性能,透過節流 (throttle) 可以將計算的這個回調函式在固定時間內合併一次被執行。
這裡不適合使用防抖的原因是,防抖只會在事件停止被觸發後的一段時間內被執行一次。因此如果用防抖,當使用者一直滑動頁面,函式就永遠不會被觸發。這邊我們仍想要函式在滑動過程中被觸發,只是不想那麼頻繁被觸發,這種情境下,節流就可以派上用場。
節流函式會接受兩個參數
- 延遲的時間 (ms)
- 要執行的回調 (callback) 函式
手寫節流 (throttle) 函式
我們先直接看程式碼,看看你能了解多少。有不懂的地方也不擔心,下面會透過註解,一行行解釋:
function throttle(fn, delay = 500) {
let timer = null;
return (...args) => {
if (timer) return;
timer = setTimeout(() => {
fn(...args);
timer = null;
}, delay);
};
}
程式碼註解版本和實際應用
function throttle(fn, delay = 500) {
let timer = null;
// throttle 本身會回傳一個函式,透過 ...args 拿到該函式的引數
return function (...args) {
// 如果有計時器,表示還在 delay 的秒數內
// 直接 return,不往下執行程式碼
if (timer) return;
// 如果計時器不等於 null,會進到以下邏輯
// 設定計時器,在 delay 秒數之後,將計時器值為改為 null
// 如果還不到 delay 的秒數,再執行一次的話
// 因為 timer 的值不為 null,前面就先 return 不會進到這段邏輯
// 可以達到 throttle 的目的,將一段時間內的操作,集合成一次執行
timer = setTimeout(() => {
timer = null;
}, delay);
// 直到時間到了後,timer 變成 null,才能夠執行函式
// 用 .apply 來呼叫,才能
fn.apply(this, args);
};
}
const updateThrottleText = throttle(() => {
console.log("throttle");
}, 500);
// 如果一直滑動畫面,會固定 500ms console.log('throttle')
window.addEventListener("scroll", () => {
updateThrottleText();
});