1. 程式人生 > >防抖debounce和節流throttle

防抖debounce和節流throttle

就會 listener timestamp search ron 存在 iat NPU 崩潰

大綱

一、出現緣由

二、什麽是防抖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));

  

防抖debounce和節流throttle