昨天講了防抖,今天輪到節流。雖然一樣都是為了節省重複執行,但兩者還是有些差異。
最後不免俗地會來個比較。
限制事件的頻繁觸發。為了解決被觸發太多次事件(例如螢幕滾動事件就會瘋狂觸發)。
用於定期需要執行的事件,以確保在短時間內只觸發一次。例:滾動事件、定時器事件。
使用者頻繁觸發事件,不論被叫了幾次,依然會是在相同的時間間隔,才執行一次事件。觸發一次函式之後,會隔一段時間才能再次執行該函式。
設置一個計時器,當事件觸發時,如果計時器沒有達到設定的時間間隔,則忽略該事件,否則執行事件處理函數並重置計時器。
有個很多篇報導的新聞頁,想要用瀑布流的方式載入很多篇新聞,一次顯示八篇,使用者到達頁底時就再載入八篇。(可能偵測到底的時候會一直打function)
function throttle(func, delay) {
let previousCall = 0; // 記錄上一次函數被呼叫的時間戳
return function(...args) {
const currentCall = new Date().getTime();
if (currentCall - previousCall >= delay) {
// 如果距離上一次呼叫已經過了指定的延遲時間
func.apply(this, args);
previousCall = currentCall;
}
};
}
// 範例函數,你可以將需要節流的函數替換成你的實際函數
function exampleFunction() {
console.log('Function executed.');
// 呼叫api、實際要執行的動作...
}
// 創建一個節流函數,設置 500 毫秒的延遲
const throttledFunction = throttle(exampleFunction, 500);
以下說明這例
throttle function
previousCall
是用來記錄時間差的變數,前一次呼叫這個函數是什麼時候。return function(...args){...}
本身是在建立一個用來包裹的函數。return **function**(...args)
,這 function 是個匿名函數。...args
是ES6的方法中的其餘運算符。用來表示其餘的參數,代表可以傳入不定數量的參數值進入函式,如果沒傳入東西會是空陣列而不是undefined。{...}
節流函式的判斷主體,用來檢查兩次觸發函式的時間差,有沒有超過 變數delay
指定的時間。exampleFunction
實際要呼叫api、實際要執行的動作之類的函數。
throttledFunction
呼叫 throttle function 並且設置 delay
時間;在過了 delay
時間,且 throttle
function擋掉多餘的觸發後,才會執行 exampleFunction
。
.bind()
用於綁定值,作為別的函數要傳入的參數;會有一個新函式產生,因此要直接命名變數成為一函數執行的結果。
.call()
可以用來call一個變數,傳入一個函式。
.apply()
跟.call()相像,只是.apply()傳入參數的形式是array。
為了避免過多次觸發事件
防抖:
想要觸發很多次,但只有最後一次成功。
第一次觸發後還是可以一直接受觸發,只是計時器會不停被更新,所以只有最後一次會成功。
節流:
想要觸發很多次,但只有第一次成功。
第一次觸發後就先停止接受觸發,時間過後才可再次觸發,所以時間間隔內,只有第一次會有效。
就是兩招記起來會很好用的方法!
今天就到這,如有說明不周或錯誤的地方,還請多留言討論(鞠躬)。
防抖節流(在二、區別中有張圖,將防抖節流和正常執行表示得很清楚 !)
https://www.readfog.com/a/1634896524109516800
其餘參數(Rest parameters)
https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part4/rest_spread.html
bind, call, apply 的差異
https://ithelp.ithome.com.tw/m/articles/10260539