scenario

There is an input box, you need to update the data according to the input content. There is a problem that if you use change, you need to lose focus to get the data. If you use keyUp, you will update the data every time you press a key. Encounter this kind of problem we can use shake to solve, as long as the user is still inputting, do not perform the operation of updating data, when the user stops the operation time N to do processing, so that you can achieve an input optimization effect.

implementation

Let’s start with the simplest implementation

function debounce(func, wait) {
  var timeout;
  return function () {
    clearTimeout(timeout)
    timeout = setTimeout(func, wait); }}Copy the code

The above demo uses the closure feature to store timeoutId in the timout variable of the upper scope. The function returned by each process will get the timeoutId, which can be used to cancel timing. According to the above description, we need to enter the time n for the last time before we execute the data processing program, so we use a timer here to delay the execution of the program. Each input cancels the last scheduled task, so the scheduled task will only be executed after the last input time N.

Then there is a problem, our function needs to get some parameters, according to the parameters to update the data, the above demo can not get parameters, we can use apply to achieve, next look at the demo with parameters

function debounce(func, wait) {
  var timeout;
  return function () {
    var context = this
    var args = arguments;
    clearTimeout(timeout)
    timeout = setTimeout(() = >{
      func.apply(this,args) }, wait); }}Copy the code

At this point, the above function has been basically realized, but it can only be executed after input n time. Can we execute the program first and then trigger the next execution at an interval of N time? Let’s improve the demo

function debounce(func, wait, immediate) {
  var timeout, result;

  return function () {
    var context = this;
    var args = arguments;

    if (timeout) clearTimeout(timeout);
    if (immediate) {
      // If yes, no further action is required
      varcallNow = ! timeout; timeout =setTimeout(function () {
        timeout = null;
      }, wait);
      if (callNow) result = func.apply(context, args);
    } else {
      timeout = setTimeout(function () {
        func.apply(context, args);
      }, wait);
    }
    return result;
  };
}
Copy the code

Complete the demo:

See the Pen debounce by Anna (@AnnaLoveLife) on CodePen.