节流或防抖:控制函数的执行

在浏览器里面有很多交互行为:点击按钮出现弹窗,滑动鼠标滚轮窗口内容随之移动,缩放浏览器窗口引起页面的重新布局,发送HTTP请求等待服务器相应等等。在这些例子中,前者(点击按钮,滑动鼠标滚轮,缩放浏览器窗口,发送HTTP请求)是事件,后者(出现弹窗,窗口内容改变)是响应,这个过程即是事件驱动。

事件驱动有一个明显缺点:事件发生很频繁就会造成性能问题。

比如:某个函数根据窗口大小来操作DOM,倘若用户在很短的时间内,频繁缩放和扩大浏览器窗口,函数就会不必要地频繁执行。因为JS是单线程的,这样,其它的事件响应可能就没有办法执行,造成页面卡顿或是无响应等。

事件发生的频率和次数没有办法控制,因此只能控制事件响应的频率或是次数,来保证正常的用户体验。

控制函数的执行频率和次数有两种方法:1、Throttle,函数节流  2、Debounce,函数防抖。

Throttle函数节流

 Throttle是节流阀的意思。1s内执行10次函数,则频率为10。如果可以控制函数执行的频率,1s内执行2次函数,则频率为2,就好像水龙头拧得小了一点。

 在页面中监听mousemove事件,移动鼠标,回调函数执行的频率会很高,可以调整其频率来保证性能,也就是在最小时间段内只能执行一次函数。

let old = 0;
const delta = 1000;
function throttleFun(fn) {
    const now = Date.now();
    if (now - old >= delta) {
      // 在1000ms内log函数只能执行一次,保证频率不能过高
      log();
      old = now;
    } else {
      // 在快速移动鼠标过程中,可以看到控制台的输出下面的内容
      // 而真正的目标函数最多也只能在1s内执行1次
      console.log("move too fast")
    }

}
function log(){
  console.log('I\'m log')
}
window.onmousemove = throttleFun;

Debounce函数防抖

对于电子器械,按下一个按钮,由于物理材料,接触情况,传导性能等因素,可能会产生多个电流信号,就好像“手抖按了多次按钮”一样。因此,“防抖机制”就很有必要,可以保证在短时间的多次操作只有最后一次操作才有效果。

防抖原理:事件第一次发生,先不响应,事件第二次发生,计算两次事件发生的时间间隔,若时间间隔小于某个值,则认为是“手抖操作”,函数仍旧不响应,事件第三次发生,计算第二次、第三次发生的时间间隔。

let old = 0;
const delta = 1000;
function debounceFun(fn) {
    const now = Date.now();
    if (now - old >= delta) {
      // 只有两次事件发生的间隔大于1000ms,log函数才会执行。保证没有误操作
      log();
    } else {
      console.log("move too fast")
    }
    // 事件发生,都需要标记事件发生的时间
    // 以便下次事件发生时,计算时间间隔
    old = now;
}
function log(){
  console.log('I\'m log')
}
window.onmousemove = debounceFun;

使用setTimeout的写法,重点在于,判断在某个时间段内,如果有一个函数在队列中,则更新队列中的函数。

let timerId;
const delta = 1000;
function debounceFun(fn) {
  if(timerId > 0) {
    // 如果大于0,则说明delta时间段内,上一个函数还没有执行
    // 直接清除,更新队列中的函数
    clearTimeout(timerId)
  }
  timerId = setTimeout(() => {
    log()
  }, delta);
}
function log(){
  console.log('I\'m log')
}
window.onmousemove = debounceFun;

[参考资料]:

1、 Timing Controls   https://zhirzh.github.io/2016/10/11/timing-controls/

2、 JS魔法堂:函数节流(throttle)与函数去抖(debounce)  http://www.cnblogs.com/fsjohnhuang/p/4147810.html

 

posted on 2018-02-05 22:17  oneplace  阅读(365)  评论(0编辑  收藏  举报

导航