debounce
與 throttle
用來防止 scroll, resize 等事件處理器在短時間內被頻繁觸發,綁定的函示重複執行,造成網頁不斷重新運算進而影響效能,作法就是控制函式觸發的次數或頻率,以下分別說明兩者的操作方式。
Debounce
概念是加入一個倒數計時器,連續觸發時會一直重新倒數,直到計時器歸零,才執行函式。
簡單舉例:
就像是便利商店的自動門,當一段時間內頻繁有客人進來,自動門會持續開著,直到大家都進入後,等待幾秒才關上。
function debounce(func, delay = 1000) { let timer = null; return function(...args) { clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); }, delay) } }
|
利用閉包(closure)將 timer 變數與內部函式分享,func.apply(this, args)
可以替換成 func.call(this, ...args)
或是 func.bind(this)(...args)
如果不太清楚函數原型方法 call、apply、bind,以及裡面代入的 this 和 argument,可以參考這一篇
範例:input 輸入搜尋事件
當輸入停止超過一秒後,才去讀取輸入內容
<input type="text" placeholder="請輸入搜尋內容" id="search" /> <p id="content"></p>
|
const input = document.getElementById('search'); const content = document.getElementById('content');
input.addEventListener('input', debounce(updateContent));
function updateContent(e) { content.textContent = e.target.value; }
|
範例畫面:
Throttle
節流器,目的是減少事件執行的次數,事件連續觸發時製造間隔來控制運行次數。
簡單舉例:
像是等紅綠燈,在固定的時間才會轉成綠燈,如果錯過了,必須等待一段時間,直到下次綠燈才能通過。
首次執行的時機:
有以下兩種,只差在首次執行,後續的結果都是一樣的。
1. 首次「立刻」執行
function throttle(func, timeout = 1000) { let isClose = false; let timer = null; return function(...args) { if (isClose) { return; } func.apply(this, args); isClose = true; clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); isClose = false; }, timeout) } }
|
2. 首次「延遲」執行
function throttle(func, timeout = 1000) { let isClose = false; let timer = null; return function(...args) { if (isClose) { return; } isClose = true; clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); isClose = false; }, timeout); } }
|
範例:scroll 視窗滾動事件
滾動視窗時,每隔一秒才執行函式,判斷是否要顯示下一區塊內容
const content = document.getElementById('content');
window.addEventListener('scroll', throttle(handleScroll));
function handleScroll() { if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { content.innerHTML += '<li> ... </li>'; } }
|
範例畫面:
debounce
與 throttle
適合的情境略有不同,可以藉由上述範例來觀察兩者間的差異
debounce
適用在停止觸發後才執行事件(input 停止輸入後,才去讀取更新的值)
throttle
適用在固定時間區間執行事件(滑鼠滾動時,每隔一秒檢查當前位置,判斷是否要撈取下一頁的資料)
參考文章:
https://medium.com/@alexian853/debounce-throttle-那些前端開發應該要知道的小事-一-76a73a8cbc39
https://ithelp.ithome.com.tw/articles/10222749
https://medium.com/@steven234/throttle跟-debounce有什麼區別-e0b1979b1b4f
評論