Implementation, difference and application scenario of anti shake and throttling

Keywords: Javascript Mobile

Application:
In our development process, there will be some user operations, such as rolling events, input events, etc., which cause repeated calls to a function, with infinite frequency, overload the browser, and page jam. At this time, anti shake and throttling will be used to control the call frequency and reduce the browser load.

Difference:
Anti shake: set A time period A to delay. If the event is not triggered again in A time period after the event is triggered, the function will automatically execute once after A time period. If the event is triggered again before A time period, the time period A will be recalculated according to the last trigger to delay execution. As shown in the following figure:

Throttling: set a time period B, after the event is triggered, execute again after time B, no matter how many times the user triggers the event, the function will only execute once every time period B;

To sum up: anti shake is to change the infinite times into the last execution, and throttling is to change the infinite times into execution every other period of time;

Realization:
Anti shake: anti shake is divided into non immediate execution and immediate execution. Non immediate execution is the execution of the function after a period of time after triggering; immediate execution is the execution of the function immediately after triggering, then wait for the specified time to pass, and then trigger again to be effective, and execute again immediately;

Non immediate execution:

<!DOCTYPE html>
<html lang="en">
 
<head>
 <meta charset="UTF-8">
 <title>Add anti shake</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>
 
<body>
 <div>
//Input after adding anti shake: not executed immediately
 <input type="text" name="debounce" id="debounce">
 <div id='box'>
//Mobile here
 </div>
 </div>
 <script type="text/javascript">
 // Anti shake
 //Non immediate execution
 var i=0;
function debounce(fn, wait) { 
    console.log("implement")
    var timeout ; 
    return function(){
      if(timeout!== null) {
          clearTimeout(timeout)
        }
      timeout = setTimeout(fn,wait);    
    }
}
// Processing function
function handle() {    
  i++;
   console.log(i+"Secondary execution")
}
//Trigger events show two examples
//Mouse movement events
 var box=document.getElementById('box');
 box.onmousemove=debounce(handle, 1000);
//Keyboard input events
var inp=document.getElementById('debounce');
inp.onkeyup=debounce(handle, 1000);
 </script>
</body>
 
</html>

Immediate execution:

<!DOCTYPE html>
<html lang="en">
 
<head>
 <meta charset="UTF-8">
 <title>Add anti shake</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>
 
<body>
 <div>
//Input after adding anti shake: execute immediately
 <input type="text" name="debounce" id="debounce">
 <div id='box'>
//Mobile here
 </div>
 </div>
 <script type="text/javascript">
 // Anti shake
 //Immediate execution
 var i=0;
function debounce(fn, wait) { 
    var timeout ; 
    return function(){
      if(timeout!== null) {
          clearTimeout(timeout)
        }
      var flag=!timeout;
      timeout = setTimeout(function(){
        timeout=null;
      },wait);   
      if(flag){
        handle()
      } 
    }
}
// Processing function
function handle() {    
  i++;
   console.log(i+"Secondary execution")
}
//Trigger events show two examples
//Mouse movement events
var box=document.getElementById('box');
 box.onmousemove=debounce(handle, 1000);
//Keyboard input events
var inp=document.getElementById('debounce');
inp.onkeyup=debounce(handle, 1000);
 </script>
</body>
 
</html>

Throttle: there are two ways to realize function throttle: time stamp and timer;
Timestamp method:

<!DOCTYPE html>
<html lang="en">
 
<head>
 <meta charset="UTF-8">
 <title>Add anti shake</title>
 <style type="text/css">
   #box{
     width:500px;
     height: 500px;
     background: red;
   }
 </style>
</head>
<body>
 <div>
    //Input after throttling: time stamp
    <input type="text" name="debounce" id="inp">
    <div id='box'>
     //Mobile here
    </div>
 </div>
 <script type="text/javascript">
//throttle
 var i=0;
var throttle = function(fn, way) {
    var prev = Date.now();
    return function() {
        var now = Date.now();
        if (now - prev >= way) {
            handle();
            prev = Date.now();
        }
    }
}
function handle() {
  i++;
    console.log(i+"frequency");
}
//Trigger events show two examples
//Mouse movement events
var box=document.getElementById('box');
 box.onmousemove=throttle(handle, 3000);
//Keyboard input events
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 3000);
</script>
</body>
 
</html>

Timer:

<!DOCTYPE html>
<html lang="en">
 
<head>
 <meta charset="UTF-8">
 <title>Add anti shake</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>
 
<body>
 <div>
//Input after throttling: timer
 <input type="text" name="debounce" id="inp">
 <div id='box'>
//Mobile here
 </div>
 </div>
 <script type="text/javascript">
 // throttle
 var i=0;
var throttle = function(fn, way) {
   var timer = null;
    return function() {
        if (!timer) {
            timer = setTimeout(function(){
              handle()
              timer=null;
            }, way);
        }
    }
}
function handle() {
  i++;
    console.log(i+"frequency");
}
//Trigger events show two examples
//Mouse movement events
var box=document.getElementById('box');
 box.onmousemove=throttle(handle, 2000);
//Keyboard input events
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 2000);
</script>
</body>
</html>

The above two methods have their own disadvantages. The timestamp does not execute the function after the last trigger, while the timer does not execute the function immediately when the first trigger. These two methods cannot perfectly meet the needs, so we optimized the throttling method as follows:

<!DOCTYPE html>
<html lang="en">
 
<head>
 <meta charset="UTF-8">
 <title>Add anti shake</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>
 
<body>
 <div>
//Input after throttling: timer
 <input type="text" name="debounce" id="inp">
 <div id='box'>
//Mobile here
 </div>
 </div>
 <script type="text/javascript">
 // throttle
var i=0;
var throttle = function(fn, way) {
    var timer = null;
    var startTime = Date.now();
    return function() {
      var nowTime = Date.now();
      var remaining = way - (nowTime - startTime);  //Remaining time
      clearTimeout(timer);
      if (remaining <= 0) {      // Immediate execution on first trigger
           handle()
          startTime = Date.now();
      } else {
        timer = setTimeout(handle, remaining);   //Cancel the current counter and calculate the new remaining
      }
    }
}
function handle() {
  i++;
    console.log(i+"frequency");
}
//Trigger events show two examples
//Mouse movement events
var box=document.getElementById('box');
 box.onmousemove=throttle(handle, 3000);
//Keyboard input events
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 3000);
 </script>
</body>
 
</html>

There is a bug in time stamp + timer version. Please correct it. Thank you!

Posted by gevo12321 on Sun, 03 Nov 2019 11:01:55 -0800