The most complete and understandable principle, implementation and optimization of debounce and throttling

    This article introduces the application and code implementation and optimization of debounce and throttling in detail. Among them, the function throttling implements the timer version and the timestamp version, and different versions are optimized.Read it patiently, you won't regret it

    1. debounce

    1.1 Definition

    Debounce means that only when a function is not triggered again within n seconds, the function will actually be executed; if the function is triggered again within n seconds, the time will be recalculated, such as: when searching, when the user stops typing Only call the method to save request resources

    1.2 Application scenarios

    • Frequently enter content in the input box, search or submit information;
    • Click the button frequently to trigger an event;
    • Listen to the browser scroll event to complete the operation;
    • The resize event when the user zooms the browser (triggered when the size of the browser window changes)

    1.3 Implementation

    Use a third-party library underscore

    js handwritten

    <body>
          <input type="text">
           <button id="cancel">cancel</button>
     </body> 
    
    1. Basic implementation of debounce function

         //Version 1, the basic implementation of the debounce function 
       <script>
          let count = 0;
         const inpt = document. querySelector('input');
         const foo = function (e) {
           console.log(`Send ${++count} request`, this, e);
         };
      
         //Basic implementation of debounce function
         function myDebounce(fn, delay) {
           // 1. Define a timer
           let timer = null;
           const _debounce = function () {
             // cancel the last timer
             if (timer) clearTimeout(timer);
             // delay execution function
             timer = setTimeout(() => {
               //Modify the fn function this point and pass parameters, otherwise this points to window and the parameter is undefined
             fn.apply(this, arguments);
             }, delay);
           };
           return_debounce;
         }
      
        //No debounce function is used
        // inpt.oninput = foo
          //Use debounce function
         inpt.oninput = myDebounce(foo, 800);
      </script>
      

    No debounce function is used

    Use debounce function


    2.Optimize the debounce function: increase the effect of immediate execution

        //Version 2, add immediate execution effect
         function myDebounce2(fn, delay, immediate = false){
           let timer = null
           let isimmediate = false
           const _debounce = function(){
                if (timer) clearTimeout(timer)
                   // Determine whether to execute immediately
               if(immediate && !isimmediate){
                   fn.apply(this,arguments)
                   isimmediate = true
               }else{
                   //Pay attention to the arrow function, otherwise this points to window
                   timer = setTimeout(()=>{
                     fn.apply(this,arguments)
                     isimmediate = false
                   }, delay)
               }
           }
           return_debounce
         }
    
        //use
        inpt.oninput = myDebounce2(foo, 500, true);
    

    3.Optimize the debounce function: increase the cancel effect (click the cancel button to cancel the sending request)

    function myDebounce2(fn, delay, immediate = false) {
        let timer = null;
        let isimmediate = false;
        const _debounce = function () {
          if (timer) clearTimeout(timer);
          // Determine whether to execute immediately
          if (immediate && !isimmediate) {
            fn.apply(this, arguments);
            isimmediate = true;
          } else {
            //Pay attention to the arrow function, otherwise this points to window
            timer = setTimeout(() => {
              fn.apply(this, arguments);
              isimmediate = false;
            }, delay);
          }
        };
    
        // Encapsulate cancel function
        _debounce. cancel = function () {
          clearTimeout(timer);
          isimmediate = false;
        };
        return_debounce;
      }
    //use
     let count = 0;
      const inpt = document. querySelector('input');
      const foo = function (e, a = '123') {
        console.log(`Send ${++count} request`, this, e, a);
      };
      let debounceres = myDebounce2(foo, 800, false);
      inpt.oninput = debounceres;
      const cancelBtn = document. querySelector('#cancel');
      cancelBtn. onclick = function () {
        console.log('cancel request');
        debounceres. cancel();
      };
    


    2. throttling

    2.1 Definition

    Throttling means that the js method will be executed once within a certain period of time, that is, the frequency of executing the function is fixed. Similar to a bus that runs every 10 minutes, no matter how many people are waiting at the bus stop within 10 minutes, it will leave on time as soon as 10 minutes arrive

    2.2 Application scenarios

    • Monitor page scrolling events;
    • mouse move event;
    • The user frequently clicks the button to operate;
    • Some design in the game (such as how often the spaceship fires missiles)

    2.3 js implementation

    Timer version

    The throttle function of the timer version has two characteristics:
    - The first time will be executed after n seconds (the timer will not be triggered until the time is up)
    - The throttling function will be executed once after the stop is triggered (because the function is delayed, its tasks have been added to the queue when the stop is triggered, so it will be executed once after the stop)

    1. Basic implementation of throttling function

      <script>
      function throttle(fn, delay){
      let  flag =true
      const _throttle = function(){
          if(!flag) return
          flag = false
          setTimeout(()=>{
              fn.apply(this, arguments)
              flag = true
          },delay)
      }
      return _throttle
      }
      </script>
      
    2. Throttling optimization: increase cancellation request and immediate execution

      //Timer version 2: cancel and execute immediately
       function throttle2(fn, delay = 500, immediate = false) {
      let flag = true
      let timer = null
      const _throttle = function () {
          if (!flag) return
          flag = false
          if (immediate) {
              console.log('immediately');
              fn. apply(this, arguments)
              immediate = false
              flag = true
          } else{
              timer = setTimeout(() => {
              fn. apply(this, arguments)
                  flag = true
                 immediate = false
              }, delay)
      
          }
      }
      _throttle. cancel = function () {
          if (timer) clearTimeout(timer)
          timer = null
          flag = true
          console.log('cancel request');
      }
      return_throttle
      }
      
      //use
      const inpt = document. querySelector("input")
      const btn = document. querySelector('#cancel')
      let counter = 0
      const inputChange = function (event) {
      console.log(`Send ${++counter} network request`, this, event)
       }
      let throttleres = throttle2(inputChange, 800, true)
      inpt.oninput = throttleres
      btn.onclick = function () {
      throttleres. cancel()
      }
      


    Use Immediate Execution



    Timestamp version

    The timestamp version of the throttling function has two characteristics:
    - It will be executed immediately after the trigger is started (because lastTime will be assigned a value of 0);
    - It will not be executed after the trigger is stopped (because this function is a synchronous task, it will make a corresponding judgment when it is triggered, so there is no situation that it will be executed after the trigger is stopped).

    1. Basic implementation of throttling function

      //version 1: basic implementation
       function throttle(fn, interval) {
       //Record the last start time
      let lastTime = 0
      const _throttle = function() {
      // Get the time when the current event is triggered
      const nowTime = new Date(). getTime()
      //Calculate whether the time interval between the  current trigger time and the last time is greater than the delay time
      if (nowTime - lastTime >= interval) {
      fn.apply(this,arguments);
      //Retain the time of the last trigger
      lastTime = nowTime;
       }
      }
      return_throttle
      }
      
    2. Throttling optimization: increase cancellation request and immediate execution

      <body>   
      <input type="text" />
      <button id="cancel">Cancel</button>
      
      <script>
      //Version 2: Add cancellation request and whether to execute it immediately
       function throttle2(fn, interval, leading = true) {
       let lastTime = 0;
       const _throttle = function () {
       const nowTime = new Date(). getTime();
      
        /* lastTime = 0 when calling for the first time, if lastTime === 0 is not added, lastTime = nowTime, and remainTime will not be less than 0
        If you choose to execute immediately, there is no need to change
      If you choose not to execute immediately, set lastTime = nowTime, that is, interval-0, and wait for the interval delay time to trigger */
        if (lastTime === 0 && !leading) lastTime = nowTime;
      
        //Triggered when the delay time is less than the interval time
        const remainTime = interval - (nowTime - lastTime);
        if (remainTime <= 0) {
          fn.apply(this, arguments);
          lastTime = nowTime;
        }
      }
      
      _throttle. cancel = function(){
          lastTime = 0
          console.log('cancel request');
      }
      
       return_throttle
      }
      
      //use
       const inpt = document. querySelector('input');
        const btn = document. querySelector('#cancel');
        let counter = 0;
        const inputChange = function (event) {
          console.log(`Send ${++counter} request`, this, event);
        };
        let throttleres = throttle2(inputChange, 1000, false);
        inpt.oninput = throttleres;
        btn.onclick = function () {
          throttleres. cancel();
        };
      </script>
      

    Using non-immediate execution

    3. The difference between debounce and throttling

    Similar point: The emergence of debounce throttling is to solve the problem of performance consumption caused by frequent triggering of something, so that network requests can be sent under appropriate conditions

    Difference: The difference between the two is that throttling is to do a certain thing at a fixed time, such as sending a request every n seconds; while debounce is only executed once when it is frequently triggered (the premise of both is frequent triggering )

    Popular posts from this blog

    大学资料分享——广工计院各个科目实验报告、课设及期末复习资料!!

    JAVA Traffic Signal Light Course Design (Source Code + Report + Video Demonstration)

    Win10 远程计算机或设备将不接受连接