Abstract: 16135843ab03bc Anti-shake and throttling can be said to be common in interviews. In fact, it is easy to understand. The following will take you a minute to understand the basic ideas and writing

This article is shared from the HUAWEI cloud community " JS anti-shake and throttling fast understanding and application ", author: Northern Lights Night. .

1. Quick-sensing anti-shake:

Anti-shake and throttling can be said to be common in interviews. In fact, it is very easy to understand. The following will take you a minute to understand the basic ideas and writing methods of anti-shake and throttling~

Before that, for example, we first define a button and bind a click event to execute the event to be triggered:

<!-- 定义一个按钮 -->
<input type="button" id="btn" value="按钮" />

<script>
// 获取标签
  var btn = document.getElementById("btn");
// 绑定事件  
  btn.addEventListener("click", real);
// 要触发的事件
  function real(e) {
    console.log("北极光之夜。");
    console.log(e);
  }
</script>

The execution is as follows:

It can be found that clicking continuously will always trigger the event. If this event is to send a request, then this is very unfriendly to the server. The same request is sent multiple times because of multiple clicks by the user, and the returned result is the same as that of only one click, which greatly increases server pressure and affects performance. Therefore, we introduce the concept of anti-shake, in simple terms, anti-shake is through setTimeout, in a certain time interval, multiple triggers into one trigger. directly look at the following example:

1. Delay execution through setTimeout:

The first method is to delay execution by setting the setTimeout timer. When you click multiple times quickly, the timer will be reset every time. Only when you do not click for a period of time, the timer can reach the condition and execute the event function.

<input type="button" id="btn" value="按钮" />
 <script>
   var btn = document.getElementById("btn");
   // 点击后触发trigger()函数,第一个参数为真实要执行的函数,第二个参数为定时器延迟时间
   btn.addEventListener("click", trigger(real, 1000));
   function trigger(fn, delay) {
     // 设置time为定时器,初始为 null
     var time = null;
      // 闭包原理,返回一个函数
     return function () {
       // 如果定时器存在清空定时器
       if (time) {
         clearTimeout(time);
       }
       // 设置定时器,规定时间后执行真实要执行的函数
       time = setTimeout(() => {
       // 将参数传递给真实执行的函数,因为箭头函数继承父级作用域,所以直接...arguments
         fn(...arguments);
       }, delay);
     };
   }
   //真实要执行函数
   function real(e) {
     console.log("北极光之夜。");
     console.log(e);
   }
 
</script>  

Among them, the principle of closure will be used to form a scope, so that the timer will not be repeated or cleared by the next click. If the closure is not clear, please see my article: https://auroras.blog.csdn.net/article/details/119520871

The results of the operation are as follows, each click is delayed. When mad, it will only be executed after stopping:

2. It will be executed for the first time by way of setTimeout, but will not be executed later:

It can be found that although the execution of the first method is delayed, the execution is also delayed when the user clicks for the first time, which is very unfriendly. Therefore, the following improvements are made to execute immediately when the first click is performed, and only the first time is effective when madly clicked, and the subsequent ones are not effective:

   <input type="button" id="btn" value="按钮" />
    <script>
      var btn = document.getElementById("btn");
      // 点击后触发trigger()函数,第一个参数为真实要执行的函数,第二个参数为定时器延迟时间
      btn.addEventListener("click", trigger(real, 1000));
     function trigger(fn, delay) {
       // 设置time为定时器,初始为 null
        var time = null;
        return function () {
         //定义一个firstClick,判断是否第一次执行,初始值为true
          var firstClick = !time;
         //第一次会立即执行
          if (firstClick) {
            fn(...arguments);
          }
           // 如果定时器存在清空定时器
          if (time) {
            clearTimeout(time);
          }
           // 设置定时器,此时firstClick会变为false,规定时间后time才会为null
          time = setTimeout(() => {
            time = null;
          }, delay);
        };
      } 
      //真实要执行函数
      function real(e) {
        console.log("北极光之夜。");
        console.log(e);
      }
 
   </script>  

The results of the operation are as follows. It will be executed immediately when it is clicked for the first time. When it is clicked madly, only the first time is valid and the others are not valid:

3. Through setTimeout, it will be executed for the first time and for the last time:

The first two are actually classic examples of anti-shake. Here is to expand the knowledge, continue to improve the above case so that it will be executed immediately when it is only clicked once. Execute for the first and last time when clicked multiple times.

   <input type="button" id="btn" value="按钮" />
    <script>
      var btn = document.getElementById("btn");
      // 点击后触发trigger()函数,第一个参数为真实要执行的函数,第二个参数为定时器延迟时间
      btn.addEventListener("click", trigger(real, 1000));
     function trigger(fn, delay) {
       // 设置time为定时器,初始为 null
        var time = null;
        return function () {
         //定义一个firstClick,判断是否第一次执行,初始值为true
          var firstClick = !time;
         //第一次会立即执行
          if (firstClick) {
            fn(...arguments);
          }
           // 如果定时器存在清空定时器
          if (time) {
            clearTimeout(time);
          }
           // 设置定时器,此时firstClick会变为false,规定时间后time才会为null
          time = setTimeout(() => {
            time = null;
            // 如果firstClick为true,执行
             if (!firstClick) {
              fn(...arguments);
            }
          }, delay);
        };
      } 
      //真实要执行函数
      function real(e) {
        console.log("北极光之夜。");
        console.log(e);
      }
 
   </script>  

The result of the operation is as follows, and it will be executed immediately when it is clicked only once. Execute for the first and last time when clicked multiple times. :

2. Quickly recognize throttling:

Throttling is actually easy to understand, reducing the frequency of triggering for a period of time. To put it simply, if you keep clicking madly, it will be executed every certain time. The biggest difference between it and anti-shake is that no matter how frequently the event is triggered, it can be guaranteed to be executed once within the specified time. The following is achieved by calculating the timestamp:

 <input type="button" id="btn" value="按钮" />
  <script>
    var btn = document.getElementById("btn");
    // 点击后触发trigger()函数,第一个参数为真实要执行的函数,第二个参数为限制时间
    btn.addEventListener("click", trigger(real, 500));
   function trigger(fn, delay) {
     // 设置bef,为上一次执行时间,初始为0
      var bef = 0;
      return function () {
      // 获取当前时间戳
        var now = new Date().getTime();
        //如果当前时间减去上次时间大于限制时间时才执行
        if (now - bef > delay) {
         // 执行函数
          fn(...arguments);
          //执行后,上次时间赋值为这次执行时间
          bef = now;
        }
      };
    }
    //真实要执行函数
    function real(e) {
      console.log("北极光之夜。");
      console.log(e);
    }
 
 </script>  

The results of the operation are as follows, and it runs at one point. If you don't stop madly, it will only be executed every 500 milliseconds. :

You can also use a timer to achieve throttling, as follows:

The execution will be delayed when the first point is achieved. If the crazy point does not stop, it will be executed at regular intervals.

 <input type="button" id="btn" value="按钮" />
    <script>
      var btn = document.getElementById("btn");
      btn.addEventListener("click", trigger(real, 500));
      function real(e) {
        console.log("北极光之夜。");
        console.log(e);
      }
      function trigger(fn, delay) {
      // flag为ture
        var flag = true;
        return function () {
         // 如果flag为true执行定时器
          if (flag) {
            setTimeout(() => {
              //到规定时间后执行函数,同时 flag = true;
              fn(...arguments);
              flag = true;
            }, delay);
          }
          // flag = false;防止一直执行
          flag = false;
        };
      }
</script>

The effect is as follows:

3. Summary:

There are many anti-shake and throttling methods, and different requirements will have different writing methods. It is important to understand the principles. Anti-shake is to use setTimeout to change multiple triggers into one trigger within a certain time interval. Throttling: is to reduce the trigger frequency for a period of time. The biggest difference between anti-shake and throttling is that no matter how frequently the event is triggered, it can be guaranteed that the function can be executed once within the specified time.

By the way, I recommend a good book to you. I just finished reading "Autumn Garden" today, the work of old man Yang Benfen. After watching it for a long time, I can't calm down. A book reflects an era. At the same time, it also reflects the purest and most simple ups and downs of the people of that era.

Click to follow, and learn about the fresh technology of Huawei Cloud for the first time~


华为云开发者联盟
1.4k 声望1.8k 粉丝

生于云,长于云,让开发者成为决定性力量