如何理解JS函數防抖和函數節流

概述

函數防抖和函數節流都是定義一個函數,該函數接收一個函數作為參數,並返回一個添加瞭防抖或節流功能後的函數。

因此可以將函數防抖和函數節流看作是一個函數工廠,負責對傳進來的函數進行相應的加工改造,然後產出一個新的帶有某種功能的函數。

函數防抖是某一時間內隻執行一次,而函數節流是間隔時間執行

假如有這樣一個場景:在某一頁面,有一個按鈕是 “加載更多”,這個按鈕的作用就是使用 ajax 從後端服務器請求更多的數據展示在頁面,我們都知道,ajax 請求的響應是一個異步的,會存在一定的響應時間,如果用戶在點擊瞭該按鈕後,立馬又點擊瞭一下該按鈕,按照常規回調函數的操作,回調函數會立馬又執行一次,那麼就是用戶短時間內點擊瞭兩次 “加載更多” 按鈕後就會執行回調函數向後端發起瞭兩次一模一樣的 ajax 請求,服務器會一一接收請求並處理返回數據,短時間內兩次請求還好,如果用戶連續點擊瞭 n 次 “加載更多” 按鈕呢?那就會短時間內向服務器發送瞭 n 次一模一樣的請求,每次後端處理 ajax 請求後返回數據後頁面就會重新再渲染一次,盡管內容沒有改變,這樣就會帶來性能上的問題,不僅為服務器帶去瞭壓力,也為瀏覽器帶來瞭不必要的渲染,這就是函數頻繁執行帶來的副作用。

那麼如何設置這個按鈕的點擊事件回調函數才能減少該函數頻繁執行帶來的副作用呢?

1. 函數防抖(debounce)

函數防抖的設計思路就是在函數執行前加一個等待時間,在這個等待時間內如果該函數又需要執行一次,就重新計算等待時間,再次等待,依次類推,直到等待時間到瞭,還沒有等到函數又需要執行的情況,才會執行這個函數。

就拿上述的場景來說,假設向後臺發送 ajax 請求的響應時間大概是在 2s 左右,那就設置這個等待時間為 2s,當用戶第一次點擊”加載更多”按鈕後,該回調函數並沒有立即執行,也就是還沒有開始發送 ajax,此時該函數在等待,如果在 2s 內用戶又點擊瞭”加載更多”,那就重新計算等待時間,再等待 2s ,此時 2s 過去瞭,用戶沒再第三次點擊”加載更多”按鈕瞭,那麼該函數就開始執行瞭,向後端發送 ajax 請求瞭。

函數防抖實現方式如下:

function debounce(fn, delay){
    let timeId = null
    return function(){
        let context = this
        if(timeId){window.clearTimeout(timeId)}
        timeId = setTimeout(()=>{
            fn.apply(context, arguments)
            timeId = null
        },delay)
    }
}

2. 函數節流(throttle)

函數節流的設計思路是在函數執行後加一個冷卻時間,函數在第一次執行時是立馬執行,但在其執行完後設置一個冷卻時間,在冷卻時間內,該函數不能再次執行,直到冷卻時間結束允許該函數執行瞭,才可以再次執行。

就拿上述的場景來說,冷卻時間假設也設置為 2s,在用戶第一次點擊”加載更多” 後按鈕的回調函數就會執行,也就是會向後臺發送 ajax 請求,此時用戶又立馬再次點擊瞭”加載更多”按鈕,由於此刻 2s 的冷卻時間還沒有到,那麼就會給第二次的函數執行加上一個延遲執行。

function throttle(fn, delay){
    let canUse = true
    return function(){
        if(canUse){
            fn.apply(this, arguments)
            canUse = false
            setTimeout(()=>canUse=true, delay)
        }
    }
}

以上就是如何理解JS函數防抖和函數節流的詳細內容,更多關於JS函數防抖和函數節流的資料請關註WalkonNet其它相關文章!

推薦閱讀: