节流函数和防抖函数学习

首先自己理解的概念:

防抖函数:防抖按照我的理解就是不管你触发多少次,都等到你最后触发后过一段你指定的时间才触发

节流函数:节流就是,不管怎么触发,都是按照指定的间隔来执行。

实例:

防抖函数例子:

基础版本:

节流函数和防抖函数学习_第1张图片

现在有个要求就是刚开始的时候也触发,最后一次也触发,并且可以配置,先写个测试页面方便测试功能,每次按空格键就会让数字加1,来测试防抖和节流函数。

节流函数和防抖函数学习_第2张图片

通过 leading 和 trailing 两个参数来决定开始和结束是否执行,如果 leading 为 true,则没次按空格都会执行一次,如果 trailing 为 true,则每次结束都会将最后一次触发执行。以防抖函数距离,如果两者都为 true,则第一次按空格会加 1,然后快速按空格,此时里面的 getUserAction 并不会执行,而是等到松手后再执行,加入 trailing 为 false,则松手后不会执行。

节流函数和防抖函数学习_第3张图片

解释一下,每次记录上次调用的时间,与现在的时间对比,小于间隔的话,第一次执行后之后就不会执行,大于间隔或在间隔时间后调用了,则重置 flag,可以与上面那个基本版的对比着看。

函数防抖的应用场景,最常见的就是用户注册时候的手机号码验证和邮箱验证了。只有等用户输入完毕后,前端才需要检查格式是否正确,如果不正确,再弹出提示语。以下还是以页面元素滚动监听的例子,来进行解析:

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

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

 函数防抖的要点,也是需要一个setTimeout来辅助实现。延迟执行需要跑的代码。
 如果方法多次触发,则把上次记录的延迟执行代码用clearTimeout清掉,重新开始。
 如果计时完毕,没有方法进来访问触发,则执行代码。

 这个方法的作用是监听ID为debounce元素的滚动事件
 进入滚动事件方法体的时候,做的第一件事就是清除上次未执行的setTimeout。而setTimeout的引用id由变量timer记录。
clearTimeout方法,允许传入无效的值。所以这里直接执行clearTimeout即可。
 然后,将需要执行的代码放入setTimeout中,再返回setTimeout引用给timer缓存。
 如果倒计时300ms以后,还没有新的方法触发滚动事件,则执行setTimeout中的代码。

 函数防抖的实现重点,就是巧用setTimeout做缓存池,而且可以轻易地清除待执行的代码。
 其实,用队列的方式也可以做到这种效果。这里就不深入了。

函数防抖:注册时邮箱的输入框,随着用户的输入,实时判断邮箱格式是否正确。此时,每一次的用户输入都触发邮箱格式检测事件,造成了浪费,于是设置两次输入之间的时间间隔大于800ms时(用户结束输入时),再执行检查邮箱格式。

 
  
[javascript]  view plain  copy
  1. const filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;  
  2. $("#email").on("keyup",checkEmail());  
  3. function checkEmail(){  
  4.     let timer=null;  
  5.     return function (){  
  6.         clearTimeout(timer);  
  7.         timer=setTimeout(function(){  
  8.             console.log('执行检查');  
  9.         },800);  
  10.     }  
  11. }  
当第一次输入事件触发,设置定时:在800ms之后执行检查。
假如只过了100ms,上次的定时还没执行,此时清除定时,重新定时800ms。
紧跟着又来了一次输入,上次定时依然没执行,再次清除定时,重新定时800ms。
...
直到最近一次的输入,后面没有紧邻的输入了,这最近一次的输入定时计时结束,终于执行了检查代码。
结果是:如果两次输入触发事件的时间间隔不足800ms的,不执行检查代码。 两次触发事件的时间间隔大于800ms了,则前面的执行检查。
这就是传说中的 函数防抖

节流

节流就是,不管怎么触发,都是按照指定的间隔来执行,同样给个基本版。

节流函数和防抖函数学习_第4张图片

同样和防抖函数一样加上两个参数,也可使用上面的例子来测试,其实两者的代码很类似。

节流函数和防抖函数学习_第5张图片

函数节流:一个加载新闻的列表页,只要滚动到页面的最下面就继续加载一部分新闻出来,即滚动加载。这时,就要监听滚动事件,判断若滚动
到页面底部了,就执行加载新闻的代码。
 
  
[javascript]  view plain  copy
  1. $(window).scroll(loadMore());  
  2.     function loadMore(){  
  3.         var canRun=true;  
  4.         return function(){  
  5.             if(!canRun){return;}  
  6.             canRun=false;  
  7.             setTimeout(function(){  
  8.                 console.log("执行滚动事件");  
  9.                 var docHeight=$(document).height();  
  10.                 var winHeight=$(window).innerHeight();  
  11.                 var scrollDistance=$(window).scrollTop();  
  12.                 if( docHeight - (winHeight+scrollDistance) <=100 ){  
  13.                     console.log('加载中...');  
  14.                 }  
  15.                 canRun=true;  
  16.             },600);  
  17.         }  
  18.     }  
由于滚动事件非常频繁,稍微滚动一下就会触发许多次,如果频繁触发的滚动,每一次都去检查是否到页面底部了再次造成了浪费。
于是设置一个开关,一次只能有一个触发执行,并对执行设置计时一段时间再执行,执行完毕之后再解锁。这就是函数节流

 函数节流应用的实际场景,多数在监听页面元素滚动事件的时候会用到。因为滚动事件,是一个高频触发的事件。以下是监听页面元素滚动的示例代码:

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

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

 函数节流的要点是,声明一个变量当标志位,记录当前代码是否在执行。
 如果空闲,则可以正常触发方法执行。
 如果代码正在执行,则取消这次方法执行,直接return

 这个方法的作用是监听ID为throttle元素的滚动事件。
 当canRuntrue,则代表现在的滚动处理事件是空闲的,可以使用。
 通过关卡if(!canRun),等于就拿到了通行证。然后下一步的操作就是立马将关卡关上canRun=false。这样,其他请求执行滚动事件的方法,就被挡回去了。
 接着用setTimeout规定最小的时间间隔300,接着再执行setTimeout方法体里面的内容。
 最后,等setTimeout里面的方法都执行完毕,才释放关卡canRun=true,允许下一个访问者进来。

 这个函数节流的实现形式,需要注意的是执行的间隔时间是>=300ms。如果具体执行的方法是包含callback的,也可以将canRun=true这一步放到callback中。理解了函数节流的关卡设置重点,其实改起来就简单多了。

demo地址:https://wall-wxk.github.io/blogDemo/2017/02/15/throttleAndDebounce.html



你可能感兴趣的:(节流函数和防抖函数学习)