淺談 函數防抖(debounce) 和函數節流(throttle)

 函數防抖(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 爲 falsefunc調用將被推遲到下一個點,類似setTimeout0的超時。 

應用場景:實時搜索(keyup)、拖拽(mousemove)

_.debounce(func, [wait=0], [options={}])

lodash在opitons參數中定義了一些選項,主要是以下三個:

leading,函數在每個等待時延的開始被調用,默認值爲false
trailing,函數在每個等待時延的結束被調用,默認值是true
maxwait,最大的等待時間,因爲如果debounce的函數調用時間不滿足條件,可能永遠都無法觸發,因此增加了這個配置,保證大於一段時間後一定能執行一次函數
根據leading和trailing的組合,可以實現不同的調用效果:

leading-false,trailing-true:默認情況,即在延時結束後纔會調用函數
leading-true,trailing-true:在延時開始時就調用,延時結束後也會調用
leading-true, trailing-false:只在延時開始時調用
deboucne還有cancel方法,用於取消防抖動調用

事例:

// 避免窗口在變動時出現昂貴的計算開銷。
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);

場景使用
function test() {
  console.log(11)
}

function debounce(method, context) {
  clearTimeout(method.tId);
  method.tId = setTimeout(function() {
    method.call(context)
  }, 500)
}
window.onresize = function() {
  debounce(test, window);
}

函數節流(throttle)

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

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

如果 wait 爲 0 並且 leading 爲 falsefunc調用將被推遲到下一個點,類似setTimeout0的超時。 

應用場景:窗口調整(resize)、頁面滾動(scroll)、搶購瘋狂點擊(mousedowm)
throttle將一個函數的調用頻率限制在一定閾值內,例如1s內一個函數不能被調用兩次。
_.throttle(func, [wait=0], [options={}])

實例:

// 避免在滾動時過分的更新定位
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);

_.throttle和_.debounce的區別:

雖然在等待時間內函數都不會再執行,但_.throttle在第一次觸發後開始計算等待時間,
_.debounce在最後一次觸發之後才計算等待時間(最後一次在等待時間範圍內)

參考資料: https://www.lodashjs.com/docs/latest#_debouncefunc-wait0-options

                  https://www.lodashjs.com/docs/latest#_throttlefunc-wait0-options

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章