函数节流,防抖

函数节流防抖

Posted by Lan on June 20, 2019

函数节流和防抖是优化高频率执行js的方法

背景

在js的实现过程中,总会有一些应用场景需要监听某些事件完成对应的需求。

较为常见的有scroll,resize,keyup等事件的监听

以scroll为例,通过监听滚动事件的触发频率来实现事件功能。但如果这种事件触发频率在短时间内过多,则对于浏览器而言是十分消耗性能的。

所以为了优化性能,提高执行效率,设置此类事件在一定时间执行一次或者在多次触发后有足够的空闲时间,才执行一次代码,这就是节流和防抖

概念

函数节流

一定时间内js方法只跑一次

函数防抖

在频繁触发的情况下,只有足够的空闲时间,才执行代码一次

换句话说就是,多次触发事件后,事件处理函数只执行一次,并且是在触发操作结束时执行的

函数节流

函数节流多用在监听页面元素滚动事件

典型代码举例:

var canRun = true;
document.getElementById("throttle").onscroll = function(){
    if(!canRun){
        // 判断是否已空闲,如果在执行中,则直接return
        return;
    }

    canRun = false;
    setTimeout(function(){
        console.log("函数节流");
        canRun = true;
    }, 300);
};

上面的代码设置滚动事件的执行时间在300毫秒执行一次,在时间结束之前,直接return,不进行实际的输出执行

const _.throttle = (func, wait) => {
  let timer;

  return () => {
    if (timer) {
      return;
    }

    timer = setTimeout(() => {
      func();
      timer = null;
    }, wait);
  };
};

函数节流的应用场景

滚动加载

谷歌搜索框,搜索联想

高频点击提交,表单重复提交

函数防抖

依据网上的说法,防抖的应用场景多在用户手机和邮箱等的验证了,具体就是等用户全部输入完毕之后,前端才检查格式是否正确,若不正确,则弹出提示语

典型代码举例:

// 函数防抖
var timer = false;
document.getElementById("debounce").onscroll = function(){
    clearTimeout(timer); // 清除未执行的代码,重置回初始化状态

    timer = setTimeout(function(){
        console.log("函数防抖");
    }, 300);
};  

这里利用一个clearTimeout()来实现在触发事件时,删除上次触发建立的定时器。

const _.debounce = (func, wait) => {
  let timer;

  return () => {
    clearTimeout(timer);
    timer = setTimeout(func, wait);
  };
};

在第一次执行时会设定定时器并等待,如果再次执行相同任务时清除定时器,重新定时

逻辑很简单,每次触发先清除定时器,之后在新建定时器,在连续高频次触发的情况下,定时器内容不会真正执行,直到最后一次触发时,没有下一次清除定时器的操作了,此时就可以保证定时器在等待时间到达后执行函数体

函数防抖应用场景

搜索框输入,最后一次输完,才发送请求 手机号邮箱验证 窗口resize。窗口调整完成后,计算窗口大小。防止重复渲染

对比

如果设想在一个简单的滚动场景下,在每一次触发滚动事件时输出一次内容,那么对于普通滚动,函数节流,函数防抖会有不同的效果

对于普通滚动,因为滚动一次就触发一次滚动事件,所以会有很多次输出,是性能消耗最高的情况。

对于函数节流下的滚动,由于函数节流是让函数在一定时间内执行一次,所以最终的执行输出会根据滚动的总时间和每次的间隔时间来来执行,相对普通滚动而言当然是较少的次数

对于函数防抖下的滚动,由于滚动是多频次触发滚动事件,所以js的输出会在多次触发的最后一次时执行一次,所以理想情况下会只有一次输出

在这里插入图片描述