防抖debounce和节流throttle

大纲

一、出现缘由

二、什么是防抖debounce和节流throttle

三、应用场景

3.1防抖

3.2节流

一、出现缘由

前端开发中,有一部分用户行为会频繁触发事件,而对于DOM操作,资源加载等耗费性能的处理,很可能导致卡顿,甚至浏览器崩溃,防抖和节流就是为了这一类的问题出现的前端优化技术。

二、什么是防抖debounce和节流throttle

防抖debounce是函数在规定延迟时间内不被调用,才能再次被调用,如果在规定时间内调用,延迟重新开始计算;

节流throttle是在规定的延迟时间间隔后,函数才执行一次,以固定的频率被触发。

三、简单实现

3.1防抖

连续触发事件的时候,不会有任何反应,停止触发事件的多少秒,就会执行,在延迟时间内执行函数,就重新开始一个定时器。

 

function debounce(func,delay=300,timer=null){
    return (...args){
        clearTimeout(timer);
        timer=setTimeout(func.bind(null,...args,delay);)
    }
}
function query(){
    //ajax
}
input.addEventListener('keyup',debounce(query))

 

  

 

3.2节流

触发事件的时候,执行一个函数,在之后的一段时间内进这个函数,会被return,真正的逻辑不能执行,定时器在一定时间后重置开关,再进来就能再次执行真正的逻辑了。

 

function throttle(func,delay=60){
    let lock=false;
    return (...args)=>{
        if(lock)reutrn;
        function(..args);
        lock=true;
        setTimeout(()=>lock=false,delay);
    }
}
function query(){
    //ajax
}
decument.addEventListener('scroll',throttle(query));

 

  

 

四、应用场景

3.1防抖throttle的应用场景

防抖适用于window.onscroll事件,等到拉动动作结束后再触发一个事件,或者拖拽

 

    _.throttle=function(func,wait,options){
        var context,args,result;
        var timeout=null;
        var previous0;
        if(!options)options={}
        var later=function(){
            previous=options.leading===false:0:new Date();
            timeout=null;
            result=func.apply(context,args);
            if(!timeout)context=args=null;
        }
        return fucntion(){
            var now=new Date();
            if(!previous && option.leading===false)previous=now;
            var remaining=wait-(now-previous);
            context=this;
            args=arguments;
            if (remaining <= 0 || remaining > wait) {
                if (timeout) {
                    clearTimeout(timeout);
                    timeout = null;
                }
                previous = now;
                result = func.apply(context, args);
                if (!timeout) context = args = null;
            } else if (!timeout && options.trailing !== false) {
                timeout = setTimeout(later, remaining);
            }
            return result;
        }
    }

 

  

 

3.2节流throttle的应用场景

下面具体讲一个例子

假设我们网站有一个搜索框,用户输入文本我们自动会联想匹配除一些结果供用户选择,我首先想到的做法是监听keypress事件或change事件,然后ajax请求数据,但是当用户快速输入的时候,就会瞬间触发一连串的请求,这无疑不是我们想要的,我们想要的是用户停止输入的时候才去触发查询的请求,这时候函数防抖可以帮助我们。

 

_.throttle=function(func,wait,immediate){
        var timeout,args,context,timestamp,result;
        var later=function(){  //如果没有超过等待时间,就接着设置一个定时器,时间是delay的时间减去方法执行的时间
            var last=new Date().getTime() - timestamp;
            if(last<wait && last>=0){
                timeout=setTimeout(later,wait-last);
            }else{   //如果已经过wait时间了,就直接清除定时器,给result赋值
                clearTimeout(timeout);
                if(!immediate){
                    result=func.apply(context.args);
                    if(!timeout)context=args=null;
                }
            }
        }
        return function(){
            context=this;
            args=arguments;
            timestamp=new Date().getTime();
            var callNow=immediate && timeout;    //如果是立即执行或者之前执行过还没过延迟时间
            if(!timeout)timeout=setTimeout(later,wait);   //如果之前没执行过,现在开始定时任务,如果执行过,timeout存在,就返回个空的result.
            if(callNow){   //如果是立即执行,就立即执行fn,这时候
                console.log(1);
                result=func.apply(context,args);
                context=args=null;
            }
            return result;
        }
    }
    function query(){
        //ajax
        console.log('ajax');
    }
    $("#search").keypress(_.throttle(query,300));

 

  

 

posted @ 2018-08-27 18:01  lingling144  阅读(330)  评论(0编辑  收藏  举报