函數節流


(1)瀏覽器滾動事件scroll

  (2)  鼠標的點擊事件 mouseup, mousedown,mousemove

  (3)  鍵盤的keyup, keydown, input事件

(4)window的resize事件

以上四個場景中,事件都是連續觸發的,如果也連續執行相應的回調函數,不但浪費資源,而且沒有意義,還有可能導致瀏覽器或者服務器崩潰。 

 

什么是函數節流和函數防抖

 

 

 

函數防抖:在一段連續操作結束后,處理回調(一次),利用 clearTimeout 和 setTimeout 實現。

應用場景: 窗口resize。 手機號、郵箱驗證輸入。搜索輸入。

函數節流:在一段連續操作中,每隔一段時間只執行一次第一次調用函數,創建一個定時器,在指定的時間間隔之后運行代碼。當第二次調用該函數時,它會清除前一次的定時器並設置另一個。如果前一個定時器已經執行過了,這個操作就沒有任何意義。然而,如果前一個定時器尚未執行,其實就是將其替換為一個新的定時器。目的是只有在執行函數的請求停止了一段時間之后才執行。

應用場景:聯想搜索。滾動監聽加載。

函數節流的原理

函數節流的原理挺簡單的,那就是定時器。當我觸發一個事件時,先setTimout讓這個事件延遲一會再執行,如果在這個時間間隔內又觸發了事件,那我們就clear掉原來的定時器,再用setTimeout設一個新的定時器延遲一會執行。

 例子場景:實現常見的搜索功能

1.沒有使用函數節流的情況下,為input綁定keyup事件處理函數,在控制台輸出我輸入的內容。

 

HTMl:
    <input id="search" type="text" name="search">
JS:
    <script>
        function queryData(text){
            console.log("搜索:" + text);
        }
        var input = document.getElementById("search");
        input.addEventListener("keyup", function(event){ queryData(this.value);
        });
    </script>

測試結果:

 

 可以看出,這種情況下,每按下一個鍵盤鍵,就輸出了一次。在性能上的消耗可想而知。

 2.使用基本的函數節流模式的情況

 

HTML:
    <input id="search" type="text" name="search">
JS:
    <script>
        function queryData(text){
            console.log("搜索:" + text);
        }
        var input = document.getElementById("search");
        input.addEventListener("keyup", function(event){
            throttle(queryData, null, 500, this.value);
            // queryData(this.value);
        });
        
        function throttle(fn,context,delay,text){
            clearTimeout(fn.timeoutId);
            fn.timeoutId = setTimeout(function(){
                fn.call(context,text);
            },delay);
        }
   </script>

 

 

問題就是,假如我不斷地輸入,輸入了很多內容,但是我每兩次之間的輸入間隔都小於自己設置的delay值,那么,這個queryData搜索函數就一直得不到調用。

實際上,我們更希望的是,當達到某個時間值時,一定要執行一次這個搜索函數。所以,就有了函數節流的改進模式。

3.改進模式

HTML:
    <input id="search" type="text" name="search">
JS:
    <script>
        function queryData(text){
            console.log("搜索:" + text);
        }
        var input = document.getElementById("search");
        input.addEventListener("keyup", function(event){
            throttle(queryData, null, 500, this.value,1000);
            // throttle(queryData, null, 500, this.value);
            // queryData(this.value);
        });
        
        function throttle(fn,context,delay,text,mustApplyTime){
            clearTimeout(fn.timer);
            fn._cur=Date.now();  //記錄當前時間

            if(!fn._start){      //若該函數是第一次調用,則直接設置_start,即開始時間,為_cur,即此刻的時間
                fn._start=fn._cur;
            }
            if(fn._cur-fn._start>mustApplyTime){ 
            //當前時間與上一次函數被執行的時間作差,與mustApplyTime比較,若大於,則必須執行一次函數,若小於,則重新設置計時器
                fn.call(context,text);
                fn._start=fn._cur;
            }else{
                fn.timer=setTimeout(function(){
                    fn.call(context,text);
                },delay);
            }
        }
   </script>

 

測試部分轉載自:https://www.cnblogs.com/LuckyWinty/p/5949970.html

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM