節(jié)流函數(shù)和防抖函數(shù)都是用來防止函數(shù)被頻繁觸發(fā)的。
函數(shù)節(jié)流與防抖需要做的是忽略一些事件請求以降低觸發(fā)回調(diào)的頻率。
節(jié)流 (throttle)
函數(shù)節(jié)流: 指定時間間隔內(nèi)只會執(zhí)行一次任務(wù)
使用場景: 滾動事件
function throttle(func, wait) {
let prev, timerId; // prev 記錄上一次函數(shù)執(zhí)行的時間,timerId 記錄計時器的id
wait || (wait = 500); // 默認(rèn)間隔為 250ms
// 返回的函數(shù),每過 wait 毫秒就執(zhí)行一次 func 函數(shù)
return function() {
let curr = +new Date();
let diff = curr - prev;
if (!prev || diff >= wait) { // 如果是第一次執(zhí)行函數(shù),
// 或者時間間隔大于我們所設(shè)置的間隔,直接執(zhí)行函數(shù),并記下當(dāng)前的時間
func();
prev = Date.now()
} else {
clearTimeout(timerId);
timerId = setTimeout(func, wait - diff)
}
}
}
防抖
函數(shù)防抖: 任務(wù)頻繁觸發(fā)的情況下,只有任務(wù)觸發(fā)的間隔超過指定間隔的時候,任務(wù)才會執(zhí)行。如果在這個時間間隔內(nèi),任務(wù)再次觸發(fā),則重新計時。
使用場景: 表單 input (比如 百度搜索 在搜索框輸入文字的時候會有提示,這個通常就是用防抖來做的。假如 你不用防抖 那么在你輸入的時候會不斷請求數(shù)據(jù)) 、resize 事件
function debounce(func,wait) {
wait || (wait = 500);
let timerId;
return function () {
clearTimeout(timerId); // 如果在wait 內(nèi)再次觸發(fā),重新計時
timerId = setTimeout(func, wait)
}
}
總結(jié)
網(wǎng)上看到一個很形象的比喻,以坐電梯為例:
函數(shù)節(jié)流 :保證在第一個人進(jìn)來后開始計時,電梯10秒后準(zhǔn)時運(yùn)行一次,不等待,如果沒有人,則不運(yùn)行
函數(shù)防抖:如果有人進(jìn)電梯(觸發(fā)事件),那電梯將在10秒鐘后出發(fā)(執(zhí)行事件監(jiān)聽器),這時如果又有人進(jìn)電梯了(在10秒內(nèi)再次觸發(fā)該事件),我們又得等10秒再出發(fā)(重新計時)。