1. 程式人生 > 實用技巧 >防抖節流模式

防抖節流模式

防抖節流模式

防抖debounce與節流throttle都是控制事件處理函式執行頻率的方法,當函式會進行DOM操作或者具有請求伺服器等行為並且作為高頻事件例如onscroll觸發的事件處理函式時,就需要進行事件處理函式執行頻率的控制,否則會造成大量的資源浪費致使效能下降,當然無論是防抖與節流實質上並沒有減少事件觸發次數,而是通過減少事件處理函式的執行次數從而提高效能。準確來說防抖節流模式不屬於通常定義的設計模式範疇,但他們是一種非常有用的程式碼構建技巧。

防抖模式

非立即防抖

當持續觸發事件的時候,事件處理函式是完全不執行的,等最後一次觸發結束的一段時間之後,再去執行。最常見的例子就是搜尋建議功能,當用戶進行持續輸入時,並不會請求伺服器進行搜尋建議的計算,直至使用者輸入完成後的N

毫秒後才會將資料傳輸至後端並返回搜尋建議。
實現思路:每次觸發事件時都取消之前的延時呼叫方法並重設定時器。

function debounce(wait, funct, ...args){
    var timer = null;
    return () => {
        clearTimeout(timer);
        timer = setTimeout(() => funct(...args), wait);
    }
}

window.onscroll = debounce(300, (a) => console.log(a), 1);

立即防抖

當持續觸發事件的時候,事件處理函式會立即執行,然後不再執行事件處理函式,直至最後一次事件觸發之後的一段時間後才允許再次執行事件處理函式。
實現思路:判斷是否存在定時器,沒有則執行事件處理函式,然後無論是否已經存在定時器都需要重設定時器。

function debounce(wait, funct, ...args){
    var timer = null;
    return () => {
        if(!timer)  funct(...args);
        clearTimeout(timer);
        timer = setTimeout(() => timer = null, wait);
    }
}

window.onscroll = debounce(300, (a) => console.log(a), 1);

節流模式

當事件持續觸發時,節流操作可以稀釋事件處理函式執行頻率,假設在1sonmousemove事件觸發了100次,通過節流就可以使得onmousemove事件的事件處理函式每100ms觸發一次,也就是在1sonmousemove事件的事件處理函式只執行10次。

時間戳實現

實現思路:通過時間戳記錄上次事件處理函式執行時間,事件觸發時若時間差大於執行週期則執行事件處理函式並賦值執行時間為當前時間戳。

function throttle(wait, funct, ...args){
    var previous = 0;
    return () => {
        var now = +new Date();
        if(now - previous > wait){
            funct(...args);
            previous = now;
        }
    }
}

window.onscroll = throttle(1000, (a) => console.log(a), 1);

定時器實現

實現思路:判斷是否存在定時器,沒有則執行事件處理函式並重設定時器。

function throttle(wait, funct, ...args){
    var timer = null;
    return () => {
        if(!timer){
            funct(...args);
            timer = setTimeout(() => timer = null, wait);
        }  
    }
}

window.onscroll = throttle(1000, (a) => console.log(a), 1);

每日一題

https://github.com/WindrunnerMax/EveryDay

參考

https://www.jianshu.com/p/566c66aafa22
https://github.com/mqyqingfeng/Blog/issues/22
https://github.com/mqyqingfeng/Blog/issues/26