首頁>技術>

在寫JS時,這兩個函式比較常見,有時候傻傻分不清用哪個,或者說知道程式碼要怎麼寫,但要說出它究竟是節流函式還是防抖函式時一臉楞逼。今天有一個同學分享了這兩個的區分,我也來回顧一下,加深一下印象,以便日後用到時心裡有底。PS:百度和谷歌搜尋前幾個介紹都是相反介紹,本文為原創,如有雷同純屬抄襲我的。

節流概念(Throttle)

按照設定的時間固定執行一次函式,比如200ms一次。注意:固定就是你在mousemove過程中,執行這個節流函式,它一定是200ms(你設定的定時器延遲時間)內執行一次。沒到200ms,一定會返回,沒有執行回撥函式的。

主要應用場景有:scroll、touchmove

防抖概念(Debounce)

抖動停止後的時間超過設定的時間時執行一次函式。注意:這裡的抖動停止表示你停止了觸發這個函式,從這個時間點開始計算,當間隔時間等於你設定時間,才會執行裡面的回撥函式。如果你一直在觸發這個函式並且兩次觸發間隔小於設定時間,則一定不會到回撥函式那一步。·

主要應用場景有:input驗證、搜尋聯想、resize

節流實現

思路: 第一次先設定一個變數true,第二次執行這個函式時,會判斷變數是否true,是則返回。當第一次的定時器執行完函式最後會設定變數為flase。那麼下次判斷變數時則為flase,函式會依次執行。

程式碼一:首次不執行

function throttle(fn,delay=100){\t//首先設定一個變數,在沒有執行我們的定時器時為null\tlet timer = null;\treturn function(){\t\t//當我們發現這個定時器存在時,則表示定時器已經在執行中,需要返回\t\tif(timer) return;\t\ttimer = setTimeout(()=>{\t\t\tfn.apply(this,arguments);\t\t\ttimer = null;\t\t},delay);\t}}

程式碼二:首次執行

function throttle2(fn,delay=100){\tlet last = 0;\treturn function(){\t\tlet curr = +new Date();\t\tif(curr - last > delay){\t\t\tfn.apply(this,arguments);\t\t\tlast = curr;\t\t}\t}}

防抖實現

思路:首次執行時把定時器賦值給一個變數,第二次執行時,如果間隔沒超過定時器設定的時間則會清除掉定時器,重新設定定時器,依次反覆,當我們停止下來時,沒有執行清除定時器,超過一定時間後觸發回撥函式。

程式碼一:首次不執行

function debounce(fn,delay=200){\tlet timer = null;\treturn function(){\t\tif(timer) clearTimeout(timer);\t\ttimer = setTimeout(()=>{\t\t\tfn.apply(this,arguments);\t\t\ttimer = null;\t\t},delay);\t}}

程式碼二:首次執行

//code from http://caibaojian.com/throttle-debounce.htmlfunction debounce2(fn, delay = 200, atBegin = true) {\tlet timer = null, last = 0,during;\treturn function () {\t\tlet self = this, args = arguments;\t\tvar exec = function () {\t\t\tfn.apply(self, args);\t\t}\t\tif (atBegin && !timer) {\t\t\texec();\t\t\tatBegin = false;\t\t} else {\t\t\tduring = Date.now() - last;\t\t\tif (during > delay) {\t\t\t\texec();\t\t\t} else {\t\t\t\tif (timer) clearTimeout(timer);\t\t\t\ttimer = setTimeout(function () {\t\t\t\t\texec();\t\t\t\t}, delay);\t\t\t}\t\t}\t\tlast = Date.now();\t}}

演示 開啟控制檯觀察變化

上面的程式碼只是我自己的一個簡單實現,看看lodash裡面的兩個核心實現程式碼。生產中建議使用它們的庫,畢竟有這麼多人在用,出bug的機會比較少,我上面的程式碼有可能有一些情況沒考慮到。如果你發現有問題的,也請告訴我。

如果在專案中有需要用到的,可以直接安裝單個的NPM模組。throttle 和 debounce

lodash使用使用文件

lodash庫裡面這兩個函式設定的引數有點複雜,記錄一下里面的引數和程式碼使用。

節流(throttle)

官方文件解釋:

建立一個節流函式,在 wait 秒內最多執行 func 一次的函式。 該函式提供一個 cancel 方法取消延遲的函式呼叫以及 flush 方法立即呼叫。 可以提供一個 options 物件決定如何呼叫 func 方法, options.leading 與|或 options.trailing 決定 wait 前後如何觸發。 func 會傳入最後一次傳入的引數給這個函式。 隨後呼叫的函式返回是最後一次 func 呼叫的結果。

注意: 如果 leading 和 trailing 都設定為 true 則 func 允許 trailing 方式呼叫的條件為: 在 wait 期間多次呼叫。

如果 wait 為 0 並且 leading 為 false, func呼叫將被推遲到下一個點,類似setTimeout為0的超時。

引數

func (Function)要節流的函式[wait=0] (number)需要節流的毫秒[options] (Object)選項物件[options.leading=true] (boolean)指定呼叫在節流開始前[options.trailing=true] (boolean)指定呼叫在節流結束後

返回值 (Function)

返回節流的函式

示例

// 避免在滾動時過分的更新定位jQuery(window).on('scroll', _.throttle(updatePosition, 100));// 點選後就呼叫 `renewToken`,但5分鐘內超過1次。var throttled = _.throttle(renewToken, 300000, { 'trailing': false });jQuery(element).on('click', throttled);// 取消一個 trailing 的節流呼叫jQuery(window).on('popstate', throttled.cancel);

防抖(debounce)

建立一個 debounced(防抖動)函式,該函式會從上一次被呼叫後,延遲 wait 毫秒後呼叫 func 方法。 debounced(防抖動)函式提供一個 cancel 方法取消延遲的函式呼叫以及 flush 方法立即呼叫。 可以提供一個 options(選項) 物件決定如何呼叫 func 方法,options.leading 與 options.trailing 決定延遲前後如何觸發(先呼叫後等待 還是 先等待後呼叫)。 func 呼叫時會傳入最後一次提供給 debounced(防抖動)函式 的引數。 後續呼叫的 debounced(防抖動)函式返回是最後一次 func 呼叫的結果。

注意: 如果 leading 和 trailing 選項為 true, 則 func 允許 trailing 方式呼叫的條件為: 在 wait 期間多次呼叫防抖方法。

如果 wait 為 0 並且 leading 為 false, func呼叫將被推遲到下一個點,類似setTimeout為0的超時。

引數

func (Function)要防抖動的函式[wait=0] (number)需要延遲的毫秒數[options] (Object)選項物件[options.leading=false] (boolean)指定呼叫在延遲開始前[options.maxWait] (number)設定 func 允許被延遲的最大值[options.trailing=true] (boolean)指定呼叫在延遲結束後

返回值 (Function)

返回具有防抖動功能的函式

示例

// 避免視窗在變動時出現昂貴的計算開銷。jQuery(window).on('resize', _.debounce(calculateLayout, 150));// 當點選時 `sendMail` 隨後就被呼叫。jQuery(element).on('click', _.debounce(sendMail, 300, { 'leading': true, 'trailing': false}));// 確保 `batchLog` 呼叫1次之後,1秒內會被觸發。var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });var source = new EventSource('/stream');jQuery(source).on('message', debounced);// 取消一個 trailing 的防抖動呼叫jQuery(window).on('popstate', debounced.cancel);

來源:前端開發部落格

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 8年Vim老司機常用外掛Top10