debounce,throttle和requestAnimationFrame簡介
debounce,throttle和requestAnimationFrame簡介
DOM 上有些事件是會頻繁觸發的,在做搜尋的時候,會出現這麼一個問題,一輸入了一點點就需要去傳送請求,但是這樣給伺服器帶來的壓力是蠻大的,可以嘗試使用一下lodash中的.debounce和.throttle。
debounce
防抖

img1
簡單講就是:不管上游事件觸發了多少次,下游就產生了一次事件。也就是說當一次事件發生後,事件處理器要等一定閾值的時間,如果這段時間過去後 再也沒有 事件發生,就處理最後一次發生的事件。假設還差 0.01 秒就到達指定時間,這時又來了一個事件,那麼之前的等待作廢,需要重新再等待指定時間。
這個就挺適合做搜尋發起請求時候用的,等到使用者keyup、keypress之後隔了xxms之後,沒有下一個動作,說明他已經完成了輸入,這時候,可以進行請求的傳送,下面給一個最簡單的例子來展示:
js部分:
//引入 import debounce from 'lodash.debounce'; //設定函式去抖 var debounceFn=debounce(function(){ //這裡進行 你想做的操作 比如發請求 什麼的 var inputVal = $("#searchInput").val(); self.searchcinemas(inputVal,city.code,{ "cityX": 121.47,"cityY": 31.23}, self.config.cinemaData,searchPageIndex,cityChange); },300); $('.schedules-block-container').find('header input').off().on('change input',function(){ debounceFn(); }).on('click', function() { this.focus(); });
throttle
節流
throttle 也就是不允許方法在每xxx ms間執行超過一次,throttle和debounce的區別在於:throttle可以保證方法每xxx ms有規律的執行。
一個相當常見的例子,使用者在你無限滾動的頁面上向下拖動,你需要判斷現在距離頁面底部多少。如果使用者快接近底部時,我們應該傳送請求來載入更多內容到頁面。
在此 .debounce 沒有用,因為它只會在使用者停止滾動時觸發,但我們需要使用者快到達底部時去請求。通過 .throttle 我們可以不間斷的監測距離底部多遠。
requestAnimationFrame (rAF)
requestAnimationFrame是另一個頻率限制的方法。requestAnimationFrame可以作為throttle的代替方法。
- 利:
- 目標60fps(16ms每貞),但是內部使用最優的時間間隔來渲染
- 使用簡單並且是標準API,以後不會變動,不需要維護
- 弊:
建議在JS執行”painting”或”animating”中直接操作屬性和重新計算元素位置時使用rAF。
傳送Ajax請求或者是否新增/刪除class(觸發一個CSS動畫)時,我會考慮debounce和throttle,此時你可以降低執行頻率(200ms而不是16ms)。
總結
使用debounce,throttle和requestAnimationFrame優化你的事件處理函式。每一個方法有一些細微的差別,三個都很有用而且互相彌補。
- debounce:把突然湧進的事件(鍵盤事件)歸為一個
- throttle:保證持續執行方法分隔為每Xms執行一次。就像每200ms監測滾動位置來觸發css動畫。
- requestAnimationFrame:throttle的替代方案,當你的方法需要重新計算和渲染元素同時你需要更平滑的變動或動畫。注意:IE9- 不支援。