After reading JavaScript Advanced Programming and some blogs on the web, I feel that the concept of function throttling and function stabilization is the opposite. The following concepts I wrote about the concept of function throttling and function stabilization depends on the concept of most people, and is based on a guest post by London-based front-end engineer David Corbacho. The article is written well, and there are corresponding codes to operate, easier to understand. In fact, I think it doesn’t matter what the name is, this method is called throttling or this method is called anti-shake, as long as you can explain it clearly and can use it in production, a name, don’t bother too much.

Avengers: Endgame represents the end of an era, and the Marvel Cinematic Universe, like the Wizarding World of Harry Potter, has been with me since 2008, when I watched the 300-megabyte Iron Man in high school. The end of an era will surely usher in a new one. The End Game?? No!

I LOVE YOU THREE THOUSANDS TIMES

I AM IRON MAN

Why anti – shake and throttling?

Anti-shake and throttling are two similar techniques, both aimed at reducing the number of times a function is fired unnecessarily in order to improve performance or avoid wasting resources. We all know that js when operating the DOM, the price is very expensive, compared to the DOM operation requires more memory and CPU time, if we have a function is in the scroll the scroll bar or change changes often trigger when the window size, or there will be a page caton, if it is a complex set of DOM logic operation, may also cause the browser to collapse. So we need to control the number of times we fire to optimize the code execution.

Mouth without evidence, we may not understand how to operate in the end, that to an example: ⬇️


      
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>I'm going to choke</title>
  <style>
    body{ height: 3000px; }
    #centerNum { width: 100px; height: 100px; line-height: 100px; text-align: center; position: fixed; left: 50%; top: 50%; transform: translate(50%, 50%); }</style>
</head>
<body>
  <h1 id="centerNum">0</h1>
  <script>
    var num = 0;
    window.onscroll = function () {
      var root = document.getElementsByTagName('body'),
      h = document.getElementById('centerNum');
      h.innerHTML = num;
      num ++;
    }
  </script>
</body>
</html>
Copy the code

We come to a window. The onscroll function, as long as the scroll, change a number of < h1 > tag, in the figure above, we can see the trigger is very frequent, if we don’t interfere, let this function is wanton trigger, not going to heaven 😡

Debounce stabilization

What is anti-shake

What is anti-shake? My own understanding is that when a method fires consecutively, the method does not execute, but executes at the end of the sequence.

For example: a straight ladder, one after another people (continuous trigger), when no people (stop continuous trigger), the elevator will close and move (implementation).

How do you do that


      
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>The elevator here</title>
  <style>

  </style>
</head>
<body>
  <button id="addBtn">The number of people in the elevator is +1</button><button id="resetBtn">reset</button>
  <p id="personNum">Number of people in elevator: 0 (assuming the elevator can hold unlimited people)</p>
  <p id="elevatorStatus">The elevator stops</p>
  <script>
    var personNum = 0; // The number of lifts
    var closeDoor = null; // Elevator start delay program
    var addBtn = document.getElementById('addBtn'); // Get the add number button
    var personNumP = document.getElementById('personNum'); // Get the label that displays the number of people
    var resetBtn = document.getElementById('resetBtn'); // Get the reset button
    var elevatorStatus = document.getElementById('elevatorStatus'); // Get the elevator status label
    /** * @method Add the number of people in the elevator * @description Click once to add one person in the elevator. When the number of people is increased, the elevator starts initialization */
    function addPerson() {
      personNum ++;
      personNumP.innerHTML = 'Number of lifts:${personNum}(assuming that the elevator can hold people indefinitely)
      initElevatorStart();
    }
    /** * @method elevator start * @description Elevator start, grey add number button, prohibit people */
    function elevatorStart() {
      elevatorStatus.innerHTML = 'Elevator start';
      addBtn.disabled = true;
    }
    /** * @method Elevator initialization * @description Clears the previous closing delay and recalculates the closing delay of 500ms, meaning that when the elevator initialization function is not triggered, the elevator will start after 500ms */
    function initElevatorStart() {
      clearTimeout(closeDoor);
      closeDoor = setTimeout(function () {
        elevatorStart();
      }, 500);
    }
    /**
     * @method 重置电梯
     */
    function reset() {
      personNum = 0;
      personNumP.innerHTML = 'Number of lifts:${personNum}(assuming that the elevator can hold people indefinitely)
      elevatorStatus.innerHTML = 'Elevator stop';
      addBtn.disabled = false;
    }

    addBtn.addEventListener('click', addPerson);
    resetBtn.addEventListener('click', reset);
  </script>
</body>
</html>
Copy the code

The above code means that I need to close the elevator door (triggering initElevatorStart()) when there is a person on the elevator, and the elevator starts. But I kept clicking on the person’s button, and the elevator is elevatorStart() method that doesn’t trigger the shutdown to start the elevator.

At the heart of the code is the initElevatorStart() method, which adds a layer of setTimeout to the elevatorStart() method that actually needs to be executed, so that the actual method needs to be executed after 500 milliseconds. If the initElevatorStart() method is triggered again within 500 milliseconds, you need to reset the timer, or you will lose money.

This is the crudest anti-shake implementation of 😳😳😳

Basic form

Here is the most basic form of this stabilization implementation, as we saw in JavaScript Advanced Programming ⬇️

var processor = {
  timeoutId: null.// a flag that is equivalent to the delay setTimeout, which can be used when clearing

  // The actual processing method
  // The code that needs to be triggered after continuous triggering stops
  performProcessiong: function () {
    // The actual code to execute
    // This is actually the code that needs to be executed when triggering is stopped
  },

  // Handle the method called initially
  // Delay the clearTimeout method around the code that actually needs to fire to control unwanted calls from successive fires
  process: function () {
    clearTimeout(this.timeoutId); // Clear the previous delay and restart the count below

    var that = this; // We need to save the scope, because the following setTimeout scope is in the window, do not call this. PerformProcessiong method we need to execute
    this.timeoutId = setTimeout(function () { Execute the performProcessiong method after 100 milliseconds
      that.performProcessiong();
    }, 100) // If it is triggered again without execution, the clearTimeout above is used to clear and restart the calculation}};// Try to start execution
processor.process(); // Need to rebind in a trigger condition
Copy the code

The above code is the most basic implementation, package in an object, and then call each other in the object, the comments should be very clear to explain what each step is, the bottom of the processor.process() we must be bound to a trigger condition in actual use, For example, in the elevator problem, we need to bind the processor.process() method to increase the number of people, so that there will be multiple calls

The above is a very simple implementation, in the actual production environment, the logic will be relatively complex, but all changes from its ancestor, understand the most basic, and then it is not a problem

Should it be called “shake forward”??

I didn’t know what it was called, Leading edge. Before we can write code clearly see that at the time of our continuous trigger a method, is really at the end of the setTimeout to perform, but there is a kind of situation, that is when we are in continuous trigger a method, for the first time trigger is executed, then the back of the continuous trigger no longer perform, such as continuous trigger stop, after a delay, Trigger again before the actual execution.

I’ll steal the map… The common form is the following

The following is written by myself, and the code implementation is also posted


      
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>The elevator here</title>
  <style>

  </style>
</head>
<body>
  <button id="addBtn">The number of people in the elevator is +1</button><button id="resetBtn">reset</button>
  <p id="personNum">Number of people in elevator: 0 (assuming the elevator can hold unlimited people)</p>
  <script>
    var personNum = 0; // The number of lifts
    var okNext = true; // Whether the command can be executed next time
    var timeoutFn = null;
    var addBtn = document.getElementById('addBtn'); // Get the add number button
    var personNumP = document.getElementById('personNum'); // Get the label that displays the number of people
    var resetBtn = document.getElementById('resetBtn'); // Get the reset button
    /** ** @method Add number * @description */ ** * @method add number * @description */
    function addPerson() {
      if (okNext) {
        okNext = false;
        personNum ++
        personNumP.innerHTML = 'Number of lifts:${personNum}(assuming that the elevator can hold people indefinitely)
      }
      clearTimeout(timeoutFn);
      timeoutFn = setTimeout(function () {
        okNext = true;
      }, 500)}/** * @method reset */
    function reset() {
      personNum = 0;
      personNumP.innerHTML = 'Elevator number: 0 (assuming the elevator can hold unlimited people)';
    }

    addBtn.addEventListener('click', addPerson);
    resetBtn.addEventListener('click', reset);
  </script>
</body>
</html>
Copy the code

If you don’t understand the above code, you can just paste it in and run it yourself and see how it feels.

Code pure I write, if there is wrong place, please big guy correct ah

Throttle orifice

What is throttling

Throttling, as I understand it, controls the number of times a method is executed during a period of time when a method is fired.

Also, for example, a subway station gate, 10 seconds into a man to execute a method (10 seconds), tube the 10 seconds to is five, 10 or 20 people, is in a person (from 10 seconds after first triggered no matter how many times will not perform is triggered, until the next 10 seconds will execute).

How?

The time stamp

We first use the timestamp to determine the time interval, and then we can know how long it has been since I last executed this method, and whether it has exceeded the time limit that I set, and if it has exceeded the time limit, I can execute again


      
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>The subway station</title>
</head>
<body>
  <button id="addBtn">Number of stops +1</button><button id="resetBtn">reset</button>
  <p id="personTotal">Total number of passengers: 0</p>
  <p id="personNum">Number of stops: 0</p>
  <script>
    var personNum = 0; // Number of arrivals
    var personTotal = 0; // How many people are there altogether
    var addBtn = document.getElementById('addBtn'); // Get the add number button
    var personNumP = document.getElementById('personNum'); // Get the label that displays the number of people
    var personTotalP = document.getElementById('personTotal'); // Get the label that shows the total number of people
    var resetBtn = document.getElementById('resetBtn'); // Get the reset button
    /** * @method increases the number of stops * @description is executed at each interval */
    function addPerson() {
      personNum ++;
      personNumP.innerHTML = 'Number of arrivals:${personNum}`;
    }
    @param {Function} fn Specifies the actual method that needs to be throttled * @param {Number} wait Specifies the length of time that needs to be controlled * @description If the time is longer than the control time, the */ can be executed
    function throttle(fn, wait) {
      var prev = 0; // The first time it is executed it is 0, so the first time it is clicked it must be greater than that, so it will be executed immediately
      return function () {
        var context = this;
        var args = arguments;
        var now = Date.now(); // The actual execution time
        personTotal ++;
        personTotalP.innerHTML = Total number of passengers:${personTotal}`;
        if (now - prev >= wait) { // If the execution time is longer than the previous execution time, the delay time is greater, we execute
          fn.apply(context, args);
          prev = now; // After execution, the last execution time is reset to the time when the function was just executed. The next execution will be based on this time}}}/** * @method reset */
    function reset() {
      personNum = 0;
      personTotal = 0;
      personNumP.innerHTML = 'Number of arrivals: 0';
      personTotalP.innerHTML = Total number of passengers: 0;
    }

    addBtn.addEventListener('click', throttle(addPerson, 1000));
    resetBtn.addEventListener('click', reset);
  </script>
</body>
</html>
Copy the code

The throttling function throttle uses scopes, call, apply, and closures. If you don’t understand, read my previous article

  1. JavaScript: Closures
  2. Call, Apply, and Bind

The above code I feel can be very intuitive to see is based on the judgment of the time before and after the two times, to know whether the next function can be executed. Refer to the comments in the code, I think it should be clear 😳😳😳

setTimeout

If we use setTimeout, we just need to change the throttle method

/** * @method Throttle method (setTimeout) * @param {Function} fn need to throttle the actual method * @param {Number} wait need to control the length of time * @description SetTimeout = setTimeout; setTimeout = setTimeout; setTimeout = setTimeout; setTimeout = setTimeout
function throttle(fn, wait) {
  var timeout = null; 
  return function () {
    var context = this;
    var args = arguments;
    personTotal ++;
    personTotalP.innerHTML = Total number of passengers:${personTotal}`;
    if(! timeout) {var that = this;
      timeout = setTimeout((a)= > {
        timeout = null;
        fn.apply(context, args)
      }, wait)
    }
  }
}
Copy the code

Although we only need to change a few lines of code are implemented using setTimeout realize throttle this approach, but we look at the map carefully, we can find that when I click on the first pit stop the passenger is not increase, it is not the same as our actual situation, we first come, I don’t have to wait, I can train directly, isn’t it. And by the time I’m done adding people, there will be one more person coming in after the waiting time, which is certainly not what we want to see.

Whether to use a timestamp or setTimeout depends on the business scenario

rAF(requestAnimationFrame)

Aye?? What is rAF? What is requestAnimationFrame? Before I wrote this blog, I had no idea there was a method under Windows.

Tell the browser that you want to execute an animation and ask the browser to call the specified callback to update the animation before the next redraw. This method takes as an argument a callback function that is executed before the browser’s next redraw. ———— MDN Web Docs

This is where we can always redraw an animation and make it look like an animation. Redrawing is a very frequent operation, so if we write it ourselves and don’t interfere, it’s a huge waste of performance and resources, so we can use requestAnimationFrame to make our animation look smooth, They don’t call it very often

advantages

  1. The goal is 60fps (16 ms per frame), and the browser will decide how best to schedule the rendering.
  2. The relatively simple and standard API will not change in the future, reducing maintenance costs.

disadvantages

  1. RAF is an internal API, so it is not convenient for us to modify
  2. If the browser TAB is not active, it won’t work
  3. Poor compatibility and still not supported in IE9, Opera Mini and older Android
  4. Cannot be used in node

Let’s use rAF

Directly above


      
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>RAF use</title>
  <style>
    #SomeElementYouWantToAnimate {
      width: 100px;
      height: 100px;
      background-color: # 000;
    }
  </style>
</head>
<body>
  <div id="SomeElementYouWantToAnimate"></div>
  <script>
    var start = null;
    var element = document.getElementById('SomeElementYouWantToAnimate');
    element.style.position = 'absolute';
    /** * @method moves our little black block */
    function step(timestamp) {
      if(! start) start = timestamp;var progress = timestamp - start;
      element.style.left = Math.min(progress / 10.200) + 'px';
      if (progress < 2000) {
        window.requestAnimationFrame(step); }}window.requestAnimationFrame(step);
  </script>
</body>
</html>
Copy the code

conclusion

RAF is an internal API, fixed execution of 16 milliseconds, because the human eye to accept 60fps animation will feel very smooth, if we need to change the rAF execution time, then we can only write their own animation method, throttling or shaking, depends on personal preference

MSC

Buffering: trigger a function consecutively, either at the start or end of the trigger, as long as it is consecutively triggered, it is executed only once

Throttling: Executes only once within a specified time, regardless of how many times it is triggered within a specified time

RAF: It is also a throttling method, native API, which aims to make animation smooth with as few resources as possible

The lodash equivalents _. Throttle and _. Debounce are recommended as best practices in my opinion

End Game

Avengers 4, the end of the Current Marvel universe, Harry Potter and Naruto, the end of one film after another, although always remind us that our youth slowly fade, just as the saying in the League of Legends, we have a new enemy called “life”. When the end is not really the end of harry potter has a fantastic beasts and where, “naruto” is for the people “, “iron man” spider-man, junior from predecessors the baton, continue to run back, we also from their own green years into the next stage of the hard work!!!!!


I’m a front end warrior, a front end elementary school.