函數節流

函數節流介紹

頁面在綁定resize,keydown或者mousemove這些能連續觸發的事件時,用戶只要很常規的操做,就能連續觸發屢次綁定的方法。當綁定方法裏面存在大量的相似於DOM操做這種極其消耗性能的代碼時,會直接致使頁面運行的卡頓。這個時候就會用到函數節流。javascript

函數節流的實現

函數節流最普通的實現就是經過取摩操做來過濾部分執行。參考代碼以下java

javascriptvar mousemoveCount = 0;
function mousemoveListener(e){
  mousemoveCount++;
  if(mousemoveCount % 2 === 0){
    return;
  }
  console.info('業務邏輯');
}

當第一次觸發並執行mousemoveListener事件時,會打印「業務邏輯」;緊接着第二次執行mousemoveListener事件時,因爲mousemoveCount爲2,會直接return掉,並不會打印「業務邏輯」。這樣子,就實現了函數節流,存在複雜計算的業務邏輯運行次數減半了。函數

可是這種實現存在兩個問題:性能

  1. 方法的執行頻率(或者說幀率)是不可控的。好比mousemove事件,執行頻率由鼠標移動速度決定,由上面這種方式實現,頻率仍是由鼠標移動速度決定。
  2. 最後一次觸發可能未執行。好比當最後一次觸發事件時,mousemoveCount是偶數,那麼會直接return。若是業務須要最後一次必須執行業務邏輯,則會存在bug。

因此就有了下面的優化實現(throttle和debounce)。優化

throttle實現

throttle又叫函數節流,思路是控制某一個時間段(執行週期)內觸發的事件,只會執行一次業務邏輯。代碼以下:code

javascriptvar lastMousemoveTime = 0, mousemoveTime = 100;
function mousemoveListener(e){
  var now = new Date().getTime();
  if(now - lastMousemoveTime <= mousemoveTime) {
    return;
  }
  lastMousemoveTime = now;
  setTimeout(function(){
    console.info('業務邏輯');
  }, mousemoveTime);
}

第一次觸發mousemove會設置100ms後執行業務邏輯,在這以後的100ms裏面觸發的mousemove都不會觸發業務邏輯。至關於控制了mousemove事件100ms觸發一次,也就是10幀。事件

使用這種實現(throttle),能夠作到觸發頻率可控。但當業務但願連續的觸發事件只在以後一次觸發後才執行業務邏輯,好比resize事件,只但願窗口變化結束後才進行業務邏輯的運行,throttle實現就不適用了。這個時候就須要使用到debounceip

debounce實現

debounce又叫函數去抖動,思路是業務邏輯在resize不在觸發後才執行。代碼以下:underscore

javascriptvar resizeTimer = null;
function resizeListener(e){
  if(resizeTimer) {
    clearTimerout(resizeTimer);
  }
  resizeTimer = setTimeout(function(){
    console.info('業務邏輯');
  }, 100);
}

但resize連續快速觸發時,業務邏輯並不會執行。只有當最後一次觸發resize後100ms,才執行業務邏輯。這種狀況就能實現只在最後一次resize觸發業務計算了。get

underscore 中已經對throttle和debounce作了實現和封裝, 有興趣能夠去查看源碼。

相關文章
相關標籤/搜索