1

认识防抖和节流

防抖

防抖,顾名思义,防止抖动,以免把一次事件误认为多次,敲键盘就是一个每天都会接触到的防抖操作。
想要了解一个概念,必先了解概念所应用的场景。在 JS 这个世界中,有哪些防抖的场景呢

  • 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖
  • 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
  • 文本编辑器实时保存,当无任何更改操作一秒后进行保存

只有在某个时间内,没有再次触发某个函数时,才真正的调用这个函数

  • 当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间
  • 当事件密集触发时,函数的触发会被频繁的推迟
  • 只有等待了一段时间也没有事件触发,才会真正的执行响应函数

防抖

节流

在飞机大战的游戏中,我们按下空格会发射一个子弹:

  • 即使按下的频率非常快,子弹也会保持一定的频率来发射;
  • 比如1秒钟只能发射一次,即使用户在这1秒钟按下了10次,子弹会保持发射一颗的频率来发射;
  • 但是事件是触发了10次的,响应的函数只触发了一次;

在某个时间内,某个函数只能被触发一次;
节流
使用场景依然是密集的事件触发,但是这次密集事件触发的过程,不会等待最后一次才进行函数调用,而是会按照一定的频率进行调用

对比

  • 防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。代码实现重在清除之前的计时器 clearTimeout
  • 节流:控制流量,单位时间内事件只能触发一次。代码实现重在开锁关锁 timer=timeout; timer=null

函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。

实现防抖函数

定义debounce函数要求传入两个参数

  • 需要处理的函数fn
  • 延迟时间

通过定时器来延迟传入函数fn的执行

  • 如果在此期间有再次触发这个函数,那么clearTimeout取消这个定时器
  • 如果没有触发,那么在定时器的回调函数中执行即可
function debounce(fn, delay) {
  var timer = null;
  return function() {
    if (timer) clearTimeout(timer);
    timer = setTimeout(function() {
      fn();
    }, delay);
  }
}

var timer=null只是对变量timer进行初始化操作
这里还用到了函数闭包,只要return后面返回的函数没有执行完毕,则timer变量会一直保持在栈空间中,不会被销毁。所以在这里timer变量只会被初始化一次,也就是第一次执行debounce防抖函数才会执行var timer=null的初始化赋值操作。

实际运用:调整Echarts的大小

  mounted() {
    var that = this;
    var timer = null;
    window.addEventListener("resize", function() {
      var delay = 500;
      if (timer) clearTimeout(timer);
      timer = setTimeout(function() {
        let myChart = echarts.init(document.getElementById(that.id));
        myChart.resize();
      }, delay);
    });
  }

第一次timer初始化为空,if(timer)里面的内容不执行,对timer进行赋值定时器。
如果在定时器结束之前(此时定时器中的函数没有被执行)再次激活监听的事件,timer不为空,所以之前的定时器被清除,然后又去设置新的定时器,直到新的定时器时间过了才执行函数。

实现节流函数

节流函数的默认实现思路我们采用时间戳的方式来完成:

  • 我们使用一个last来记录上一次执行的时间
  • 每次准备执行前,获取一下当前的时间now
  • 如果 now - last > interval,那么函数执行,并且将now赋值给last即可
function throttle(fn, interval) {
  var last = 0;

  return function() {
    // this和argument
    var _this = this;
    var _arguments = arguments;

    var now = new Date().getTime();
    if (now - last > interval) {
      fn.apply(_this, _arguments);
      last = now;
    }
  }
}

参考

https://mp.weixin.qq.com/s/qy... (主要看这个)
https://blog.csdn.net/YuT_ian...
https://zhuanlan.zhihu.com/p/...


jingyi
1 声望0 粉丝