On the Internet about anti – shake and throttling articles, large probability are copied each other, basically the same. Today I talk about the characteristics and differences between them from the perspective of xiaobai.

I. Application scenarios

  • Input box. Users frequently operate the input box to match keywords or request interfaces.
  • windowresizeOr pagescrollThings that need to be called back after a scroll adjustment, such as lazy image loading, page component sizing, etc.
  • socketPush data, such as stock trading data, is not the background push what is fully displayed what, appropriate missing part is reasonable. For example, if the background pushes hundreds of data within 100ms, real-time DOM manipulation will not only waste performance, resulting in page lag and false death, but also not much difference between a 200ms rendering and real-time rendering for users’ senses.
  • mousedown,mousemove,keyup,keydownSuch as frequent mouse operation.
  • Other scenarios that require limited frequency and do not require real-time operation.

The common feature of anti – shake and throttling is to reduce the high frequency to low frequency to achieve the purpose of performance optimization. The difference is that the former uses certain means to execute the last operation on the ground, while the latter executes at most once within 300ms.

Two, what is anti – shake

Take the input field as an example to enter content and request an HTTP interface. If the user enters 123456789 and does nothing else, listens to the input in real time and requests the interface once the input changes. Nine requests are generated. If there are 10W users operating online at the same time, the pressure on the background students can be imagined, and many requests are wasted, and the data returned by the interface for the first time may be later than that returned by the fifth request. At this time, it is necessary to do the optimization of anti-shake: real-time monitoring of input data changes, as long as there is no change for 300ms, the request interface. That is, 300ms does not change, then it is considered that the keyword users want to search is the current content. At this point you can probably understand what anti-shake is: for a certain period of time, no more frequent operation, the purpose is to ensure that the last frequent operation is actually executed, the rest is invalid

// A simple version of anti-shake
var timer = null;
function debounce(){
  if(timer) clearTimeout(timer);
  timer = setTimeout(function(){
    console.log('Window size has changed')},300)}window.addEventListener('resize',debounce);
Copy the code

The code above means that when you increase or decrease the size of the browser window, you do not actually perform the operation until 300ms after the operation is stopped, which largely avoids unnecessary waste. The above method can be very vivid to help understand the anti-shake, but need to be encapsulated, after all, such low code can not reflect the high-end level, not suitable for multiple places on the page to call, the use of closure appropriate encapsulation, convenient multiple places to call at will

function debounce(fn,delay){
  var timer = null;
  return function(){
    if(timer) clearTimeout(timer);
    timer = setTimeout(function(){
      fn.apply(this)
    },delay)
  }
}
window.addEventListener('resize',debounce(function(){
  console.log('Window size has changed')},300));
Copy the code

In the example above, the actual value of this always points to the window(browser side), and can be modified as appropriate to the actual scenario and to the execution environment

function debounce(fn,delay){
  var timer = null;
  return function(){
    if(timer) clearTimeout(timer);
    var self = this,args = arguments;
    timer = setTimeout(function(){
      fn.apply(self,args)
    },delay)
  }
}
window.addEventListener('resize',debounce(function(e){
  console.log(this)
  console.log(e)
},300));
Copy the code

Fn. Call (self,args) instead of fn(args). The key is the first parameter, making sure the context is the current this.

Thought 1: How to controlImage stabilizationFunction, which is also executed at the beginning, right?

What does that mean? Just add another switch, and we know that the anti-shake is the last of the frequent operations, but I want to do both the first and last of the frequent operations. There is nothing wrong with this idea, such as frequent operation of 5 seconds to see the result, this 5 seconds is equivalent to blank, the user may see a blank thing, if the first time to perform, present the content out, is better than always blank. Implementation idea: add a switch, if the need to execute immediately and switch is allowed to execute immediately, no delay, and immediately close the switch.

function debounce(fn,delay,immediate){
  var timer = null;
  var isImmediate = false;
  return function(){
    if(! isImmediate && immediate){ isImmediate = immediate; fn.apply(this.arguments)}else{
      if(timer) clearTimeout(timer);
      var self = this,args = arguments;
      timer = setTimeout(function(){
        fn.apply(self,args)
      },delay)
    }
  }
}
window.addEventListener('resize',debounce(function(e){
  console.log(this)
  console.log(e)
},300.true));
Copy the code

Thought 2: How to cancel delayed execution?

We know in the last image stabilization is event operation delay N seconds after, if we set the delay time is 5 seconds, then the frequent operation after we have to wait for 5 seconds, because of some special circumstances, such as have another button to trigger the cancel delay and subsequent operations, this how to do? So let’s build on that

function debounce(fn,delay,immediate){
  var timer = null;
  var isImmediate = false;
  var de = function(){
    if(! isImmediate && immediate){ isImmediate = immediate; fn.apply(this.arguments)}else{
      if(timer) clearTimeout(timer);
      var self = this,args = arguments;
      timer = setTimeout(function(){
        fn.apply(self,args)
      },delay)
    }
  }
  de.cancel = function(){
    clearTimeout(timer);
    timer = null;
    console.log('It's been canceled.')}return de
}
var resizeFn = debounce(function(e){
  console.log(e)
},5000.true)
window.addEventListener('resize',resizeFn);
// Cancel the operation
document.querySelector('.calcenButton').addEventListener('click'.function(){
  resizeFn.cancel();
})
Copy the code

What is throttling

Take the stock socket push trading port as an example, assuming that the background pushes 1W times of data within 1s, if we render the 1W times to the page, surely the page will fake dead, but also a lot of consumption of browser performance. If you change it to fetch the data source every 300ms and render to the page, the maximum rendering will be three times in 1s, which greatly reduces performance. This is throttling. Use plain language description is: the event you execute, I only interval a period of time to execute once. At this point, it feels like we can write the throttling function:

function throttle(fn,wait){
  var pre = 0;
  return function(){
    var self = this,args = arguments;
    var now = +new Date(a);if(now - pre > wait){
      pre = now;
      fn.apply(self,args)
    }
  }
}
window.addEventListener('resize',throttle(function(){
  console.log('Window size has changed')},1000));
Copy the code

The above is the use of time stamps, with the event operation driver throttling, let’s switch to a timer implementation. The idea is: set a timer, every time the execution of the time if the timer exists is ignored, if it does not exist then set a timer, if the timer is executed, the timer will be empty after re-timing.

function throttle(fn,wait){
  var timer = null;
  return function(){
    var self = this,args = arguments;
    if(! timer){ timer =setTimeout(function(){
        timer = null;
        fn.apply(self,args)
      },wait)
    }
  }
}
window.addEventListener('resize',throttle(function(){
  console.log('Window size has changed')},1000));
Copy the code

The above are the two common throttling methods. The difference is that timestamp throttling will trigger execution immediately, and the rest events exceeding the wait multiple will be ignored. Timer throttling always delays the wait time, and if the event operation is stopped, it may delay the wait time again.