Debounce

Concept: anti-shake (execute the callback function n seconds after the event is triggered, and reset the timer if it is triggered again within n seconds)

Using the keyUp event of an input box as an example, let’s look at an example without stabilization:

<div> <span> Input: </span> <inputtype="text" id="inputA"> </div> <script> // Simulate an Ajax requestfunction ajax(content){
      console.log('ajax request' + content);
    }
    let inputA = document.querySelector('#inputA');
    inputA.addEventListener('keyup'.function(e){
      ajax(e.target.value);
    });
</script>
Copy the code

When we keep typing, the result is as follows:

Based on the above concept, we will first try to implement a simple version of anti-shake:

<div> <span> Input: </span> <inputtype="text" id="inputB"> </div> <script> // Anti-shake initial versionfunction debounceFn1(func, wait) {
      let timer = null;
      return(... args) => { timer && clearTimeout(timer); timer =setTimeout( () => {
          func.apply(this, args);
        }, wait); }}let inputB = document.querySelector('#inputB');
    let debounceAjax = debounceFn1(ajax, 500);
    inputB.addEventListener('keyup'.function(e){
      debounceAjax(e.target.value);
    })
</script>
Copy the code

When we keep typing, the result is as follows:

The basic function is achieved, but this method does not run our request code immediately. If we need to run the request code immediately, we can add a parameter to it.

// Add instant buffeting versionfunction debounceFn2(func, wait, immediate) {
  let timer = null;
  return(... args) => { timer && clearTimeout(timer); // The key to implementing only the first immediate execution is the variable timer, which is a variable referenced in the closure and will not be destroyed immediately // So the timer is only null at initialization, and then always has a value, which stores the timer IDif(immediate && ! timer) { func.apply(this, args); } timer =setTimeout( () => {
      func.apply(self, args);
    }, wait); }}let debounceAjax = debounceFn2(ajax, 500, true);
inputB.addEventListener('keyup'.function(e){
  debounceAjax(e.target.value);
})
Copy the code

When values are entered quickly, the result is as follows:

Underscore (debounce) a function for daily buffeting needs is basically written, and if you need more, see how underscore implements debounce.

Throttle

Concept: a function can be fired only once in a unit of time. If it is fired multiple times in a unit of time, only once takes effect.

Throttling is divided into two implementation methods, respectively with a timestamp and a timer, the following first look at a timestamp implementation chestnut:

<div> <span> Throttled input: </span> <inputtype="text" id="inputC"</div> <script> // function throttle (timestamp version)function throttleFn1(func, wait) {// Time of last executionlet previous = 0;
      return(... Args) => {// Current execution timelet now = +new Date();
        if(now - previous > wait) { previous = now; func.apply(this, args); }}}let throttleAjax = throttleFn1(ajax, 1000);
    inputC.addEventListener('keyup'.function(e){
      throttleAjax(e.target.value);
    })
</script>
Copy the code

The core of this approach to throttling is to execute the callback function only when the time difference between the two functions is greater than the wait time, and set this execution time to the comparison time, so that the callback function is always executed only once during the wait time interval. When entering a number quickly, the above code executes as follows:

Another way to implement throttling is to use a timer similar to the anti-shake implementation, and the duration of the timer is the wait value. The implementation code is as follows:

// Throttling version (timer version)function throttleFn2(func, wait) {
  let timer = null;
  return(... args) => {if(! timer) { timer =setTimeout(() => {
        func.apply(this, args);
        timer = null;
      }, wait); }}}let throttleAjax = throttleFn2(ajax, 1000);
inputC.addEventListener('keyup'.function(e){
  throttleAjax(e.target.value);
})
Copy the code

When typed quickly, the result is as follows:

Application scenarios

  • About the offer
    • A typical application scenario is associative queries for search terms in the example above. We certainly don’t want to search every time we type, so setting an interval to prevent shaking can reduce the number of invalid requests.
    • Resize window triggeredresizeEvent, which can only trigger a callback event once if the wait time is set properly and adjusted quickly.
  • About the throttle
    • When listening for browser scrollbar events, we need to check the scrollbar height periodically but not too often to use throttling

section

Function stabilization and throttling, introduced to improve code performance, is a way to optimize performance by reducing unnecessary requests and browser resource consumption (such as redraw and reflux).

After all, stabilization and throttling make use of function closures to cache state value variables so that frequent function calls can be filtered according to certain rules. The above is my personal read some big guy’s article after the summary, the code is a little bit of a hand after the verification, interested in children’s shoes can be copied after the verification, of course, there is a lack of understanding welcome message pointed out!

reference

  • [Advanced stage 6-4] Simple and profound anti-shake function
  • 7 minutes to understand the throttling, anti-shaking and application scenarios of JS
  • Underscore for JavaScript topics
  • Function anti-shake and throttling
  • 2019 Interview preparation – JS Anti-shock and throttling