防抖和節流(立即執行/非立即執行/立即取消等待/傳參)


先看看概念

函數防抖(debounce):

在事件被觸發n秒后再執行回調,如果在這n秒內又被觸發,則重新計時;典型的案例就是輸入搜索:輸入結束后n秒才進行搜索請求,n秒內又輸入的內容,就重新計時。

應用場景:

  • search搜索聯想,用戶在不斷輸入值時,用防抖來節約請求資源。
  • window觸發resize的時候,不斷的調整瀏覽器窗口大小會不斷的觸發這個事件,用防抖來讓其只觸發一次

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <button id="btn">第一次點擊按鈕立即執行 接下來 防抖</button>
        <button id="btn2">終止</button>
    </body>
    <script>
      var btn = document.getElementById('btn');
      let b= 2
      let f =  debounce_2(sayHi,2000,true)
      btn.addEventListener('click',()=>{
        f(b)
      })
      btn2.addEventListener('click',()=>{
        f.stop()
      })
      // 防抖(非立即執行)
      function debounce_1(fn,wait){
        let timer = null;
        return function(){
          clearTimeout(timer);
          timer = setTimeout(() => {
            fn.apply(this,arguments)
          },wait)
        }
      }
    
      // 防抖立即執行
      function debounce_2(fn,wait){
        let time = null
        let flag = true
        return function (){
          clearTimeout(time)
          if(flag){
            fn.apply(this,arguments)
            flag = false
          }
          time = setTimeout(()=>{
            flag = true
          },wait)
        }
      }
    
      // 防抖自定義第一次是否執行
      function debounce_3(fn,wait,isImmediate = true){
        let flag = true
        let time = null
        if(isImmediate){
          if(flag){
            return function (){
              fn.apply(this,arguments)
              flag = false
            }
          }
          clearTimeout(time)
          time = setTimeout(()=>{
            flag = true
          },wait)
        }
        return function (){
          clearTimeout(time);
          time = setTimeout(() => {
            fn.apply(this,arguments)
          },wait)
        }
      }
    
      // 防抖自定義第一次是否執行 且可中斷執行
      function debounce_4(fn, wait = 500, isImmediate = false) {
        // 計時器
        let timerId = null;
        // flag為真時立即執行
        let flag = true;
        let resultFunc = null;
        if (isImmediate) {
          // 立即執行
          //  例如:用戶在輸入框中輸入字符,輸入第一個字符時,立即執行一次
          // 之后,最終間隔超過2秒后,才執行補全查詢
          resultFunc = function () {
            let context = this;
    
            clearTimeout(timerId);
            if (flag) {
              fn.apply(context, arguments);
              flag = false
            }
            timerId = setTimeout(() => {
              flag = true
            }, wait)
          }
    
          resultFunc.cancel = function () {
            // 例如,用戶打字很快,然后輸入完成后,未達到兩秒鍾就移動鼠標
            // 此時輸入框失去焦點,觸發取消等待方法,立刻執行補全查詢操作並顯示結果出來
    
            console.log("立即取消等待")
            clearTimeout(timerId);
            flag = true;
          }
    
        } else {
          // 不立即執行
          //  例如:用戶在輸入框中輸入字符,最終間隔超過2秒后,才執行補全查詢
    
          resultFunc = function () {
            let context = this;
    
            clearTimeout(timerId);
            timerId = setTimeout(() => {
              fn.apply(context, arguments)
            }, wait)
          }
    
          resultFunc.cancel = function () {
            console.log("立即取消等待");
            clearTimeout(timerId);
          }
        }
        return resultFunc;
      }
    
      function sayHi(b) {
        console.log(b)
        console.log('防抖')
      }
    </script>
    </html>

     

     

函數節流(throttle):

規定在一個單位時間內,只能觸發一次函數,如果這個單位時間內觸發多次函數,只有一次生效; 典型的案例就是鼠標不斷點擊觸發,規定在n秒內多次點擊只有一次生效。

應用場景:

  • 鼠標不斷點擊觸發,mousedown(單位時間內只觸發一次)
  • 監聽滾動事件,比如是否滑到底部自動加載更多,用throttle來判斷

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <button id="btn">第一次點擊按鈕立即執行 接下來 節流</button>
    <button id="btn2">終止</button>
    </body>
    <script>
      var btn = document.getElementById('btn');
      let b= 2
      let f =  throttle_4(sayHi,3000)
      btn.addEventListener('click',()=>{
        f(b)
        // throttle_3(sayHi,3000)(b) 不能這么寫,因為這相當於每次都重新聲明了這個節流函數
      })
      btn2.addEventListener('click',()=>{
        f.stop()
      })
      //節流(非立即執行)
      function throttle_1(fn,wait){
        let flag = true;
        return function(){
          if(flag == true){
            flag = false
            var timer = setTimeout(() => {
              fn.apply(this,arguments)
              flag = true
            },wait)
          }
        }
      }
      //節流(立即執行)
      function throttle_2(fn,wait){
        var flag = true;
        var timer = null;
        return function(){
          if(flag) {
            fn.apply(this,arguments);
            flag = false;
            timer = setTimeout(() => {
              flag = true
            },wait)
          }
        }
      }
      //節流(自定義是否立即執行)
      function throttle_3(fn,wait = 500,isImmediate = false){
        let flag = true;
        let timer = null;
    
        if(isImmediate){
          return function(){
            if(flag) {
              fn.apply(this,arguments);
              flag = false;
              timer = setTimeout(() => {
                flag = true
              },wait)
            }
          }
        }
    
        return function(){
          if(flag == true){
            flag = false
            var timer = setTimeout(() => {
              fn.apply(this,arguments)
              flag = true
            },wait)
          }
        }
      }
      //節流(自定義是否立即執行且可以中斷)
      function throttle_4(fn, wait = 500, isImmediate = false) {
        let flag = true;
        let timer = null;
    
        let resultFunc = null;
    
        if (isImmediate) {
          // 立即執行
          resultFunc = function () {
            if (flag) {
              fn.apply(this, arguments);
              flag = false;
              timer = setTimeout(() => {
                flag = true
              }, wait)
            }
          }
    
          resultFunc.cancel = function () {
            console.log("立即取消等待")
            clearTimeout(timer)
          }
        } else {
          // 不立即執行
          resultFunc = function () {
    
            if (flag == true) {
              flag = false
              timer = setTimeout(() => {
                fn.apply(this, arguments)
                flag = true
              }, wait)
            }
          }
    
          resultFunc.cancel = function () {
            console.log("立即取消等待")
            clearTimeout(timer);
            flag = true;
          }
        }
    
        return resultFunc;
    
      }
      
      function sayHi(b) {
        console.log(b)
        console.log('節流')
      }
    </script>
    </html>

     

 


免責聲明!

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



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