In the actual development, the function must be the most practical part of the most frequent, whether function as the core of functional programming, or more people choose object-oriented programming, there will be a function of the figure, so it is very necessary to conduct in-depth research on the function.


Function of the throttle

To put it bluntly, function throttling is to enforce the maximum number of times that a function can be executed in a period of time. For example, if a function is executed at most once every 100 milliseconds, the function will be executed at most 100 times within 10s(10000ms /100ms)

The concepts of throttling and anti-vibration are easy to confuse here, so many of the key definitions in this article, translated here, move to the difference-between-throttling-and debouncing

In the browser, DOM manipulation is very frequent consumption of memory and CPU time, such as listening to resize, touchmove, scroll… Etc., constantly triggering callbacks as the DOM changes. Current front-end frameworks such as React and Vue put forward the concept of virtual DOM, which combines multiple DOM operations into one real operation using the Diff algorithm, thus greatly reducing the frequency of DOM operations. However, this is not a discussion of diff algorithms (you can poke the link above if you are interested), but rather how setTimeout can be used to reduce the risk of frequent DOM operations.

The first time I encountered this concept was in the final chapters of Elevation 3.

The basic idea behind function throttling is that some code cannot be executed continuously and repeatedly without a break. The first time the function is called, a timer is created that runs the code after a specified interval. When the function is called a second time, it clears the previous timer and sets another.

The encapsulation method is also relatively simple, and this problem is also addressed in the book:

  function throttle(method,context) {
    clearTimeout(method.tId);
    method.tId = setTimeout(function(){
       method.call(context)
      },1000)
  }Copy the code

The timer is used to delay the execution of the function for 1 second. If you throttle the function again within 1 second, delete the last timer, cancel the queue task called last time, and reset the timer. This ensures that the function will be fired only once in a second, achieving the purpose of function throttling

You can test this with the resize event;

   var  i = 0;
   function handler(){
       console.log(i++);
    }
   window.onresize = function(){
       throttle(handler,window)
   }Copy the code

You can see that switching landscape/portrait only triggers once in the debug mode of the browser

Function image stabilization

Function stabilization specifies that two conditions must be met for the function to be executed again:

  • 1. must wait for some time.
  • 2. The waiting time will not be triggered again within the waiting time of condition 1. Once the waiting time is triggered again within the waiting time of condition 1, the waiting time will be calculated again.

For example, a function is buffered for 100ms, and then the function is called 1000 times discontinuously in 3s(3000ms), and the call stops after 3s. It will only execute once at a time of 3100ms.

For the implementation code, take a look at the _. Debounce source in underscore. Js:

// Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for // N milliseconds. If `immediate` is passed, trigger the function on the // leading edge, instead of the trailing. _.debounce = function(func, wait, immediate) { var timeout, args, context, timestamp, result; var later = function() { var last = _.now() - timestamp; if (last < wait && last >= 0) { timeout = setTimeout(later, wait - last); } else { timeout = null; if (! immediate) { result = func.apply(context, args); if (! timeout) context = args = null; }}}; return function() { context = this; args = arguments; timestamp = _.now(); var callNow = immediate && ! timeout; if (! timeout) timeout = setTimeout(later, wait); if (callNow) { result = func.apply(context, args); context = args = null; } return result; }; };Copy the code

The wait argument represents debounce time, and _.now() returns a timestamp of the current time, also in ms. If immediate is passed, the callback function is triggered immediately.

Application Scenarios:

  • When using the Autonavi address associative input prompt, ajax requests are made only when the user stops keyboard typing
  • ElementUI inputNumber calculator component, in order to prevent the user clicks, the number automatically increase or decrease, also use the anti-shake operation, can be viewed source code

References:

  • the-difference-between-throttling-and-debouncing
  • Discussion on javascript function throttling (Tencent full end AlloyTeam team Blog)
  • JavaScript function throttling
  • Function anti – shake and throttling