节流和防抖

229 阅读2分钟

当resize,onScroll,或者一些表单change的事件频繁触发的时候,会频繁调用相应的事件处理函数,这很影响浏览器的执行效率,也影响到用户的体验。所以当一些事件会高频率发生的时候,可以采用防抖和节流两种方式进行处理。

节流

原理:一段时间内只允许一个事件发生,也就是当前事件必须与前一个事件间隔大于delay的事件,当前的事件才会执行

节流主要有时间戳和计时器两种实现方式:

时间戳实现节流:

这种实现方式,当第一次触发事件的时候,事件处理函数一定会被调用,最后一次可能会被调用也可能不会被调用。

function throttle(fn,delay){
       var preTime=new Date();
       return function(...args){
           var refThis=this;
           var nowTime=new Date();
           if(nowTime-preTime>delay){
               fn.apply(refThis,args);
               preTime=new Date();
           }
        }
    }
    function fn(){
        console.log("触发函数节流")
    }
    window.addEventListener("resize",throttle(fn,1000))

计时器实现节流:

这种第一次触发事件会等到delay事件之后才会执行,最后一次可能会也可能不会被触发。

function throttle(fn,delay){
       var timer=null;
       return function(..args){
           var refThis=this;
             if(!timer){
             timer=setTimeout(function(){
                 fn.apply(refThis,args);
                 timer=null;
             },delay)
         }
    }
    }
    function fn(){
        console.log("触发函数节流")
    }
    window.addEventListener("resize",throttle(fn,1000))

节流还可以采用时间戳和计时器结合的方法。

防抖

原理:只有当delay时间段内没有事件发生,才会触发事件,每次事件发生的时候,如果delay时间内有触发则会重新记时。

无论与之前的事件执行有没有间隔大于delay,都要clear掉事件执行器,如果小于,这时候之前的setTimeout计时器还没有执行,要清除之前的定时器。如果大于,之前的定时器已经执行,这时候清除也没有什么影响,所以最好的做法是,当事件触发的时候,清除掉之前的定时器,然后定义一个新的延时定时器

 function debounce(fn,delay){
        var timeout;
        return function(){
            var refThis=this;
            var arg=arguments;
            if(timeout){
                clearTimeout(timeout);
            }
            timeout=setTimeout(function(){
                fn.apply(refThis,arg);
            },delay)
        }

    }
    function fn(){
        console.log("触发函数防抖")
    }
    window.addEventListener("resize",debounce(fn,1000))