簡單介紹JS函式防抖和函式節流

大雄45發表於2021-05-28
導讀 函式防抖和函式節流都是對函式進行特殊的設定,減少該函式在某一時間段內頻繁觸發帶來的副作用。二者只是採用的設定方式和原理不一樣,其最終的目的是一樣的。
概述

函式防抖和函式節流都是定義一個函式,該函式接收一個函式作為引數,並返回一個新增了防抖或節流功能後的函式。

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

假如有這樣一個場景:在某一頁面,有一個按鈕是 "載入更多",這個按鈕的作用就是使用 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函式防抖和函式節流的詳細內容。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2774504/,如需轉載,請註明出處,否則將追究法律責任。

相關文章