防抖與節流的區別與實現

  • 2021 年 10 月 20 日
  • 筆記

防抖和節流

前言

  • 作為前端開發中會以下兩種需求
    1. 搜索需求

    搜索的邏輯就是監聽用戶輸入事件,等用戶輸入完成之後把數據發送給後端,後端返回匹配數據,前端顯示數據到頁面。如果只要用戶輸入就發請求,這樣會給後端造成請求壓力,需要控制請求的頻率。

    1. 頁面無限載入數據

    頁面無限載入數據的邏輯就是監聽用戶用戶滾動事件,在用戶滾動的過程中,去請求下一頁的數據來顯示到頁面。,那麼只要滾動就去發請求,同樣會造成後端請求壓力,需要控制請求的頻率。

  • 以上兩種看起來都是控制請求頻率的問題,但是需求有細微的差別:搜索是用戶在輸入中輸入多次,只有等用戶短暫停止輸入之後,就去發送請求,此時就需要防抖去實現。滾動載入數據是在用戶滾動頁面的過程中每間隔一段時間就去請求,即使用戶一直滾動,都會去請求,而不是等用戶停止滾動才去請求,此時就需要使用節流去實現。

防抖

  1. 含義

簡單的理解方式就是:用戶多次觸發事件,在用戶一直觸發事件中,事件不會執行,只有在用戶停止觸發事件一段時間之後再執行這個事件一次。

  1. 實現
    // @fn 是對應請求數據
    // @ms 是用戶多次觸發事件的時間間隔 是一個毫秒數
    function debounce(fn, ms) {
        let timeout = null
        return function() {
            clearTimeout(timeout)
            timeout = setTimeout(() => {
                fn.apply(this, arguments)
            }, ms)
        }
    }
  1. 原理

用戶每一次觸發事件都會延遲執行,在設置延遲定時器執之前都會把上一次延遲定時器清除,最終只有用戶連續觸發這個事件的間隔時間超出我們設置的參數ms毫秒之後,該事件才會觸發一次

  1. 測試
    <input id="searchInput"/>
    function getData(){
        console.log('發送請求...')
    }
    document.getElementById('searchInput').oninput = debounce(getData, 800)
    // 如果用戶一直在輸入,是不會發送請求
    // 只有用戶連續輸入時間間隔超過800ms之後才會請求一次數據,也就是用戶在800ms內沒有輸入才會去請求數據

節流

  1. 含義

簡單的理解方式就是:用戶多次觸發事件,在用戶一直觸發事件過程中事件會每間隔一段時間執行一次,會執行多次。

  1. 實現
    // @fn 是對應請求數據
    // @ms 是用戶多次觸發事件的時間間隔 是一個毫秒數
     function throttle(fn, ms){
        let flag = true
        return function(){
            if(!flag) return
            flag = false
            setTimeout(()=>{
                fn.apply(this, arguments)
                flag = true
            }, ms)
        }
    }
  1. 原理

用戶每一次觸發事件都會設置一個延遲定時器,但是如果已經設置了延遲定時器就會等上一次延遲定時器執行之後才會開啟下一個定時器,這樣用戶一直觸發事件,事件會每間隔一段時間執行一次

  1. 測試
    function getData(){
        console.log('發送請求...')
    }
    window.onscroll = throttle(getData, 800)
    // 用戶在滾動的過程中,會間隔去請求數據

總結

節流和防抖本質上都是控制事件執行的頻率,但是觸發事件的時機本質上有區別,防抖是在用戶多次觸發事件,當用戶停止觸發事件,將事件執行一次;節流是用戶多次觸發事件,會在多次觸發的過程中,間隔執行事件。

Tags: