Debounce & Throttle in React - 2


Posted by backas36 on 2022-04-05

上一篇講完了 debounce 之後,接下來是 throttle。

身為一個不完美又老的工程師,在初學的時候我看到這兩個名詞我就想逃走。

不過該面對的還是要面對,debounce 和 throttle 不做終究還是會要去面對 server 負擔過大的問題, server 負擔過大,你終究還是要面對前端互動不順的問題。

先對 debounce 和 throttle 做個總結,我們再來看 throttle 怎麼使用 react 實現:

debounce

在一段時間內只能執行 function 一次。
假設你現在正在做一台 300 毫秒內就會開始移動到你指定樓層的電梯,這時候突然進來了路人甲,你按下了開門鍵,於是開始等 300 毫秒,再上樓之前又突然進來了路人乙,於是又按下了開門鍵,重新計時 300 毫秒,這時候再進來了路人丙......。
無限循環的話你就永遠不能上樓,這就是 debounce,一直到都沒有人進來,這台電梯完美的等待完 300 毫秒過去。

throttle

固定的一段時間內呼叫 function
throttle 也稱為節流,debounce 稱防抖,我也不知道為什麼要叫防抖,但我不是很能理解防抖,但是節流聽起來比較親民,所以我才在這裡特別說明 throttle 是節流,debounce 我直接不介紹 XD:)
既然是節流、節流、節流,那就很好理解了,就是要稀釋掉執行 function 的頻率。
例如說呢,如果假日的高速公路交流道沒有實施節流的話,幾百台車子想要從台南交流道北上就北上,那這樣高速公路會多可怕?!所以通常在高峰期間會有節流措施,設置一個固定秒數的紅綠燈,固定一段時間放行,這就是 throttle 的概念。

接下來是 throttle 在 react 的應用:

第一個 input 是讓 user 輸入的欄位, Crazy Btn 是一個 click 之後就會根據 user 輸入的 input 去 fetch data 的 button。

    <>
      <div>
        <input value={inputValue} onChange={onInputValue} />
      </div>

      <div>
        <button onClick={onClickThrottle}>Crazy Btn</button>
      </div>
    </>

接下來是 onClickThrottle 和一些必要的 function:

const throttle = (fn, wait = 1000) => {
    let isWait = false ;
    return (...args) => {
      if(!isWait){
        fn(...args)
        isWait = true
        setTimeout(()=>isWait=false,wait)
      }
    }

  };
const throttleHandler = useCallback(throttle(fetchData, 3000), []);

const onClickThrottle = () => {
    throttleHandler(inputValue);
    console.log('fire onClickThrottle');
  };

button 綁定了 click 事件,按下之後觸發了 onClickThrottle => throttleHandler 帶著 user 的 input (inputValue) 執行 throttle(fetchData, 3000)

也就是當 click 下去之後會執行一次 fetchData ,可是在 3000 秒內怎麼 click 都不會再執行 fetchData。

可以再拉近一點看怎麼實作 throttle function 的,當我們執行 throttleHandler 的時候實際上是執行

(...args) => {
      if(!isWait){
        fn(...args)
        isWait = true
        setTimeout(()=>isWait=false,wait)
      }
}

isWait 一開始是 false ,所以當這個 function 被執行的時候就會是確認不是在等待時間內才可以下一步 => 之後執行一次 fn(...args),也就是 fetchData => 將等待狀態(isWait)改成 true => 把紅綠燈轉成紅燈,也就是開始計時 3000 秒,並且在 3000秒的時候把 isWait 改成 false。

這邊附上完整的 throttle in react 程式碼,
https://stackblitz.com/edit/react-a6kfhz?file=src/App.js

如果有錯誤或者是有任何問題,歡迎與我聯繫~










Related Posts

寫一個簡單堪用的 ESLint plugin

寫一個簡單堪用的 ESLint plugin

PHP 和 MySQL 的互動 1 : 連線

PHP 和 MySQL 的互動 1 : 連線

AppWorks School Batch #16 Front-End Class 學習筆記&心得(駐點階段四:個人專案~重構)

AppWorks School Batch #16 Front-End Class 學習筆記&心得(駐點階段四:個人專案~重構)


Comments