概述
- 函數(shù)防抖: 任務(wù)頻繁觸發(fā)的情況下,只有任務(wù)觸發(fā)的間隔超過指定間隔的時候,任務(wù)才會執(zhí)行。
- 函數(shù)節(jié)流: 指定時間間隔內(nèi)只會執(zhí)行一次任務(wù),原本可能會無時無刻執(zhí)行的函數(shù)。
總之都是為了節(jié)省計算資源。
函數(shù)防抖(debounce)
場景:
- 如今很多網(wǎng)站為了提高用戶體驗,不會再輸入框失去焦點的時候再去判斷用戶名是否被占用,而是在輸入的時候就在判斷這個用戶名是否已被注冊。當用戶輸入第一個字符后的一段時間內(nèi)如果還有字符輸入的話,那就暫時不去請求判斷用戶名是否被占用。
- 用戶注冊時候的手機號碼驗證和郵箱驗證
任務(wù)頻繁觸發(fā)的情況下,只有足夠的空閑時間,才執(zhí)行代碼一次。
基本思想:通過閉包保存一個標記(timeout)來保存 setTimeout 返回的值,每當用戶輸入的時候把前一個 setTimeout clear 掉,然后又創(chuàng)建一個新的 setTimeout,這樣就能保證輸入字符后的 interval 間隔內(nèi)如果還有字符輸入的話,就不會執(zhí)行 fn 函數(shù)了。
函數(shù)防抖的要點:也是需要一個setTimeout來輔助實現(xiàn)。延遲執(zhí)行需要跑的代碼。
如果方法多次觸發(fā),則把上次記錄的延遲執(zhí)行代碼用clearTimeout清掉,重新開始。
如果計時完畢,沒有方法進來訪問觸發(fā),則執(zhí)行代碼。
// 函數(shù)防抖
function debounce(handlerFunc, interval = 300) {
let timeout = null;
return function () {
clearTimeout(timeout);
timeout = setTimeout(() => {
handlerFunc.apply(this, arguments);
}, interval);
};
}
//綁定監(jiān)聽
window.addEventListener('resize', () => {
debounce(this.onResize, 40)
}, false);
函數(shù)節(jié)流(throttle)
場景:過多的DOM相關(guān)操作可能會導(dǎo)致瀏覽器掛起,有時候甚至會崩潰。比如:onresize、onscroll、mousemove等。
為了避免類似問題,就可以使用定時器對該函數(shù)進行節(jié)流。
基本思想:某些代碼不可以在沒有間斷的情況下連續(xù)重復(fù)執(zhí)行,就是一定時間內(nèi)函數(shù)只執(zhí)行一次。
第一次調(diào)用函數(shù),創(chuàng)建一個定時器,在指定的時間間隔之后運行代碼。當?shù)诙握{(diào)用函數(shù)時,它會清除前一次的定時器并設(shè)置另一個。如果前一個定時器尚未執(zhí)行,就是將其替換為一個新的定時器,目的是只有在執(zhí)行函數(shù)的請求停止了一段時間之后才執(zhí)行。
函數(shù)節(jié)流的要點:聲明一個變量(resizeTimeout)當標志位,記錄當前代碼是否在執(zhí)行。
- 如果空閑,則可以正常觸發(fā)方法執(zhí)行。
- 如果代碼正在執(zhí)行,則取消這次方法執(zhí)行。
注意:只要是代碼周期性執(zhí)行的,都應(yīng)該使用節(jié)流,但是并不能控制請求執(zhí)行的速率。
// 函數(shù)節(jié)流
function throttle(handlerFunc, timeout = 66) {
let resizeTimeout;
if (!resizeTimeout) {
resizeTimeout = setTimeout(() => {
resizeTimeout = null;
handlerFunc();
// The actualResizeHandler will execute at a rate of 15fps
}, timeout);
}
}
//綁定監(jiān)聽
window.addEventListener('resize', () => {
throttle(this.onResize, 40)
}, false);
總結(jié)
函數(shù)防抖和函數(shù)節(jié)流的名字起得易混淆,要找技巧理解記憶,通俗易懂的說:
- 函數(shù)防抖就像快遞小哥先將外賣攢著一起,只有規(guī)定間隔內(nèi)沒有其他配單的時候,才集中送一次。
-
函數(shù)節(jié)流就像王者榮耀中人物釋放技能之后,需要CD冷卻時間過了,才可以再放。
王者英雄王昭君
像這樣,是不是就好理解這兩個概念了
