Step by step understand JS anti – shake

Forget about “anti-shock” and “throttling”.

First look at a requirement scene, click “add roaming speed” in the picture below, and the pop-up prompt will disappear after 2 seconds. At this point, if crazy click plus, then speed prompt popup will be crazy show hide. But that’s not what we want.

demand

  • 1. Click the plus or minus button normally to display the speed prompt popup window, and hide the popup window 2 seconds later
  • 2. Click the “add” or “subtract” button continuously (interval short) to display the speed prompt pop-up window. After the operation stops, the pop-up window will be hidden 2 seconds later

solution

  • 1. When the speed changes, perform the popup display, define the setTimeOut timer, and execute the hidden popup 2 seconds later
  • 2. In normal cases, the user clicks only once, and the above code is normal. If the user clicks frequently, the code 1 is executed several times, and the clearTimeout timer is required
  • 3. ClearTimeout Indicates the clear timer. The original timer is executed after 2 seconds
  let speedChangeTimer;
  cameraWalkOperator.bindChangeSpeedCallback(() = > {
    console.log("Change in velocity");
    this.setState({
      tipSpeed: true});clearTimeout(speedChangeTimer);
    speedChangeTimer = setTimeout(() = > {
      this.setState({
        tipSpeed: false}); },2000);

    let speed = cameraWalkOperator.getSpeed();
    this.setState({
      speedValue: speed,
    });
  });
Copy the code

Image stabilization

Encapsulate the above code

// This is a closure function
function debounce(func, wait) {
  let timer;
  return function () {
    clearTimeout(timer);
    timer = setTimeout(function () {
      func();
    }, wait)
  }
}
Copy the code

Closures: You can use closures if you want to keep a variable (timer) inside a function after it has finished executing.

Closures can be understood as separating variables by declaring them in the parent scope and putting other statements in the child scope and returning them as a function

Online version

function debounce(method,delay) {
  var timer=null;
  return function () {
    var context = this, args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function () { method.apply(context,args); },delay); }}Copy the code

To understand this arguments apply; See my article at juejin.cn/post/684490…

Pay attention to

  • If you look at the code, you can see that the function returned is not executed
  • General binding document on listening. When using addEventListener (‘ mousemove ‘debounce)
  • If we’re just using it in general, and don’t listen for dom binding events, then add () to run
  • As shown in the figure below, this stabilization is actually invalid because every time the function is executed, debounce is executed again and is different.

Want to understand the addEventListener binding event principle. Please look at my article

define

Definition: When an event is triggered, the policy sets a period to delay the execution of the action. If the event is triggered again, the policy sets the period until the end of the period to execute the action.

Deep anti-shake and throttling

Debounce

Anti-shake – After the event is triggered, the event that triggers very frequently is combined into one execution.

That is, only one callback is executed within the specified time. If the event is triggered again within the specified time, the execution time of the callback function restarts based on that time.

Examples from life

In the case of card swiping, as long as the passenger keeps swiping the card, the driver can’t drive. After the passenger swipes the card, the driver will wait for a few minutes to make sure the passenger sits firmly before driving. If a new passenger gets on the bus during the last waiting period, the driver will have to wait a little longer for all passengers to be seated before starting the bus.

Code implementation

function debounce(fn, delay) {
  // Declare the timer
  let timer = null;

  // Use closure to save timer
  return function () {
    let _this = this;
    let args = arguments
    clearTimeout(timer); // The timer will be empty if the anti-shake function is called again
    timer = setTimeout(function () {
      fn.apply(_this, args); // Declare the timer (if the event is triggered again within the specified time, the execution time of the callback function restarts based on that time)}, delay); }}function down () {
  console.log('down');
}

elementHtml.addEventListener('click',debounce(dj,1000))
// 1. Bind a handler on the click event, in which case debounce is immediately called, the function that is actually returned within debounce of the bound function.
// 2. Each time an event is triggered, the current timer is cleared and the timeout call is reset.
// 3. The command can be executed after the delay time only after the last event is triggered.
Copy the code

Throttle

Throttling – When events are frequently triggered, event callbacks are executed only for a specified period of time.

That is, the callback function is executed only when the event interval is greater than or equal to the specified time.

Difference: Anti-jitter and throttling are different in nature. Anti-jitter means to turn multiple executions into the last one, and throttling means to turn multiple executions into periodic executions

Examples from life

The faucet in life, tightening the faucet to a certain extent will find that every once in a while, there will be water droplets out.

Code implementation

Timer edition – Closure

function throttle (fn, delay) {
  // Declare the timer
  let timer = null;

  // Use closure to save timer
  return function () {
    let _this = this;
    let args = arguments;

    if(! timer) {// Set the timer if there is no timer. (The throttling function using the timer is not executed on the first trigger, but after the delay seconds, so the function will be executed again when the last trigger is stopped.)
      timer = setTimeout(function () {
        fn.apply(_this, args);
        timer = null; // Empty the timer after execution}, delay); }}}Copy the code

Timestamp version – closure

function throttle (fn, delay) {
  // Declare the previous timestamp
  let prev = Date.now();

  return function () {
    let _this = this;
    let args = arguments;

    // Declare the current timestamp
    let now = Date.now();
    if (now - prev >= delay) { // If the timestamp difference is greater than or equal to the interval, the function passed in is executed. (The timestamp throttling function is executed immediately after the first event is triggered, and after every delay second, and the last event is not executed.)
      fn.apply(_this, args);
      prev = Date.now(); // Set the previous timestamp after execution}}}Copy the code

Comparison of Application Scenarios

Image stabilization

  • 1. Every time resize/scroll triggers the statistics event
  • 2. Verify text input. Send Ajax request for verification after continuous text input

The throttle

  • 1.DOM element drag function implementation
  • 2. Search associations
  • 3. Calculate the distance the mouse moves
  • 4. Canvas simulates the canvas function
  • 5. Mousedown/KeyDown events in shooters – only one bullet can be fired per unit of time
  • 6. Listen for scroll events to see if more are automatically loaded at the bottom of the page

conclusion

Function stabilization: Combine several operations into one operation. The idea is to maintain a timer that fires after the delay, but if it fires again within the delay, the timer will be cancelled and reset. In this way, only the last operation can be triggered.

Function throttling: causes functions to fire only once in a given period of time. The principle is to trigger the function by judging whether a certain time has been reached.