白话debounce和throttle
遇到的問題
在開發(fā)過程中會遇到頻率很高的事件或者連續(xù)的事件,如果不進(jìn)行性能的優(yōu)化,就可能會出現(xiàn)頁面卡頓的現(xiàn)象,比如:
為了解決這類問題,常常使用的方法就是throttle(節(jié)流)和debounce(去抖)。throttle(節(jié)流)和debounce(去抖)都是用來控制某個函數(shù)在一定時間內(nèi)執(zhí)行多少次的解決方案,兩者相似而又不同。
下面就具體的看看兩者的相似和區(qū)別。
認(rèn)識throttle和debounce
throttle和debounce的作用就是確認(rèn)事件執(zhí)行的方式和時機,以前總是不太清楚兩者的區(qū)別,容易把二者弄混。
下面就通過兩個簡單的場景描述一下debounce和throttle,以后想到這兩個場景就不會再弄混了:
debounce 假設(shè)你正在乘電梯上樓,當(dāng)電梯門關(guān)閉之前發(fā)現(xiàn)有人也要乘電梯,禮貌起見,你會按下開門開關(guān),然后等他進(jìn)電梯; 如果在電梯門關(guān)閉之前,又有人來了,你會繼續(xù)開門; 這樣一直進(jìn)行下去,你可能需要等待幾分鐘,最終沒人進(jìn)電梯了,才會關(guān)閉電梯門,然后上樓。所以debounce的作用是,當(dāng)調(diào)用動作觸發(fā)一段時間后,才會執(zhí)行該動作,若在這段時間間隔內(nèi)又調(diào)用此動作則將重新計算時間間隔。
throttle 假設(shè)你正在乘電梯上樓,當(dāng)電梯門關(guān)閉之前發(fā)現(xiàn)有人也要乘電梯,禮貌起見,你會按下開門開關(guān),然后等他進(jìn)電梯; 但是,你是個沒耐心的人,你最多只會等待電梯停留一分鐘; 在這一分鐘內(nèi),你會開門讓別人進(jìn)來,但是過了一分鐘之后,你就會關(guān)門,讓電梯上樓。所以throttle的作用是,預(yù)先設(shè)定一個執(zhí)行周期,當(dāng)調(diào)用動作的時刻大于等于執(zhí)行周期則執(zhí)行該動作,然后進(jìn)入下一個新的時間周期。
簡單實現(xiàn)
有了上面的了解,就可以去實現(xiàn)簡單debounce和throttle了。
debounce實現(xiàn)
首先來看看debounce的實現(xiàn),根據(jù)前面對debounce的描述:
可以在Chrome中運行下面的代碼,看看debounce的效果,代碼Github鏈接:
var debounce = function(action, delay) {var timer = null; return function() { var self = this, args = arguments; clearTimeout(timer); timer = setTimeout(function() { action.apply(self, args) }, delay); } } // example function resizeHandler() { console.log("resize"); } window.onresize = debounce(resizeHandler, 300);throttle實現(xiàn)
throttle跟debounce的最大不同就是,throttle會有一個閥值,當(dāng)?shù)竭_(dá)閥值的時候action必定會執(zhí)行一次。
所以throttle的實現(xiàn)可以基于前面的debounce的實現(xiàn),只需要加上一個閥值,代碼Github鏈接:
var throttleV1 = function(action, delay, mustRunDelay) {var timer = null, startTime; return function() { var self = this, args = arguments, currTime = new Date(); clearTimeout(timer); if(!startTime) { startTime = currTime; } if(currTime - startTime >= mustRunDelay) { action.apply(self, args); startTime = currTime; } else { timer = setTimeout(function() { action.apply(self, args); }, delay); } }; };其實,對于上面的實現(xiàn)可以進(jìn)心簡化,只是通過閉包維護(hù)一個開始的時間:
var throttleV2 = function(action, delay){var statTime = 0; return function() { var currTime = +new Date(); if (currTime - statTime > delay) { action.apply(this, arguments); statTime = currTime ; } } } // example function resizeHandler() { console.log("resize"); } window.onresize = throttleV2(resizeHandler, 300);總結(jié)
通過前面的介紹,應(yīng)該對debounce和throttle有一個直觀的認(rèn)識了:
- debounce:把觸發(fā)非常頻繁的事件合并成一次執(zhí)行
- throttle:設(shè)置一個閥值,在閥值內(nèi),把觸發(fā)的事件合并成一次執(zhí)行;當(dāng)?shù)竭_(dá)閥值,必定執(zhí)行一次事件
了解了throttle和debounce之后,下面看看他們的常用場景:
debounce
- 對于鍵盤事件,當(dāng)用戶輸入比較頻繁的時候,可以通過debounce合并鍵盤事件處理
- 對于ajax請求的情況,例如當(dāng)頁面下拉超過一定返回就通過ajax請求新的頁面內(nèi)容,這時候可以通過debounce合并ajax請求事件
throttle
-
對于鍵盤事件,當(dāng)用戶輸入非常頻繁,但是我們又必須要在一定時間內(nèi)(閥值)內(nèi)執(zhí)行處理函數(shù)的時候,就可以使用throttle
- 例如,一些網(wǎng)頁游戲的鍵盤事件
-
對于鼠標(biāo)移動和窗口滾動,鼠標(biāo)的移動和窗口的滾動會帶來大量的事件,但是在一段時間內(nèi)又必須看到頁面的效果
- 例如對于可以拖動的div,如果使用debounce,那么div會在拖動停止后一下子跳到目標(biāo)位置;這時就需要使用throttle
轉(zhuǎn)載于:https://www.cnblogs.com/gluncle/p/9945009.html
總結(jié)
以上是生活随笔為你收集整理的白话debounce和throttle的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用docker部署mysql主从复制集
- 下一篇: kali:用TheFatRat攻击win