函数节流

函数节流介绍

页面在绑定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作了实现和封装, 有兴趣能够去查看源码。

相关文章
相关标签/搜索