JavaScript 高階系列之節流 [throttle] 與防抖 [debounce]

深谷逸風發表於2017-11-15

一、概念

這兩個東西都是為了專案優化而出現的,官方是沒有具體定義的,他們的出現主要是為了解決一些短時間內連續執行的事件帶來效能上的不佳和記憶體的消耗巨大等問題;
像這類事件一般像 scroll keyup mousemove resize等等,短時間內不斷的觸發,在效能上消耗是非常大的,尤其是一些改變DOM結構的操作;

節流[throttle]與防抖[debounce]非常相似,都是讓上述這類事件在規定的事件從不斷的去觸發更改成為規定的時間內觸發多少次;

節流[throttle]

節流通俗來解釋就比如我們水龍頭放水,閥門一開啟,水嘩嘩的往下流,這個秉著勤儉節約的優良傳統美德,我們要把水龍頭關小點,最好是如我們心意按照一定規律在某個時間間隔內一滴一滴的往下滴,這,,,好吧這就是我們節流的概念;
換成函式來說,使用setTimeout方法,給定兩個時間,後面的時間減去前面的時間,到達我們給定的時間就去觸發一次這個事件,這麼說太籠統的,我們看下面的函式,這裡我們以【scroll】為例;

/** 樣式我就順便寫了 **/
<style>
    *{padding:0;margin:0;}
    .scroll-box{
        width : 100%;
        height : 500px;
        background:blue;
        overflow : auto;
    }    
    .scroll-item{
        height:1000px;
        width:100%;
    }
</style>

------------------------

/** 先給定DOM結構;**/
<div class="scroll-box">
    <div class="scroll-item"></div>
</div>

------------------------

/**主要看js,為了簡單我用JQ去寫了**/
<script>
    $(document).ready(function(){
        var scrollBox = $('.scroll-box');
        //呼叫throttle函式,傳入相應的方法和規定的時間;
        var thro = throttle(throFun,300);
        //觸發事件;
        scrollBox.on('scroll' , function(){
            //呼叫執行函式;
            thro();
        })

        // 封裝函式;    
        function throttle(method,time){
            var timer = null;
            var startTime = new Date();
            return function(){
                var context = this;
                var endTime = new Date();
                var resTime = endTime - startTime;
                //判斷大於等於我們給的時間採取執行函式;
                if(resTime >= time){
                    method.call(context);
                    //執行完函式之後重置初始時間,等於最後一次觸發的時間
                    startTime = endTime;
                }
            }
        }
        function throFun(){
            console.log('success');
        }
    })
</script>複製程式碼

通過以上的函式,我們就可以做到節流的效果,在規定的每300毫秒觸發一次,當然時間可以自定義,根據需求來;

防抖[debounce]

寫程式碼之前,我們先清楚一下防抖的概念,不知道大家有沒有做過電腦端兩邊懸浮廣告視窗的這麼一個東西,當我們拖動滾動條的時候,兩邊的廣告視窗會因為滾動條的拖動,而不斷的嘗試著去居於中間,然後你就會看到這兩個視窗,不停的抖啊抖;

一般這種就叫抖動了,我們要做的就是防止這種抖動,稱為防抖[debounce ];

那這裡防抖思想就是當我們拖動完成之後,兩邊的視窗位置再重新去計算,這樣,就會顯得很平滑,看著很舒服了,最主要的操作DOM結構的次數就大大減少了;

優化了頁面效能,降低了記憶體消耗,不然你像IE這種比較老點版本的瀏覽器,說不定就直接給你蹦了

用書面一點的說法就是,在某個事件沒有結束之前,函式不會執行,當結束之後,我們給定延時時間,然他在給定的延時時間之後再去執行這個函式,這就是防抖函式;

來看程式碼:

//將上面的throttle函式替換為debounce函式;
function debounce(method,time){
    var timer = null ;
    return function(){
        var context = this;
        //在函式執行的時候先清除timer定時器;
        clearTimeout(timer);
        timer = setTimeout(function(){
            method.call(context);
        },time);
    }
}複製程式碼

思路就是在函式執行之前,我們先清除定時器,如果函式一直執行,就會不斷的去清除定時器中的方法,知道我們操作結束之後,函式才會執行;

其實書寫的方式有很多,主要還是思路的問題,大家寫的多了,自然就知道了;

用途

  1. 當我們做keyup像後臺請求檢驗的時候,可以使用防抖函式,不然我們每按一次鍵盤就請求一次,請求太頻繁,這樣當我們結束按鍵盤的時候再去請求,請求少很多了,效能自然不用說;
  2. resize 視窗大小調整的時候,我們可以採用防抖技術也可以使用節流;
  3. mousemove 滑鼠移動事件我們既可以採用防抖也可以使用節流;
  4. scroll 滾動條觸發的事件,當然既可以採用防抖也可以採用節流;
  5. 連續高頻發的事件都可以採用這兩種方式去解決,優化頁面效能;

具體的採用哪一種更較為合適,主要還是看你的業務需求,好了,本篇就到這裡了,感謝大家閱讀;


手打不易,總結不易,轉載請註明出處,感謝;

相關文章