04 implementation of anti shake throttling. Q: what is the difference between anti shake throttling

Anti chattering throttling function

Anti shake function

  1. The callback function is executed at the specified time when the last event is triggered
  2. After triggering the high-frequency event, the function will be executed only once in n seconds. If the high-frequency event is triggered again in n seconds, the time will be recalculated
Click event anti shake

Click multiple times and only execute the last triggered event. Using the characteristics of closures, return is a function in the debounce function.

<script>
    let btn = document.querySelector('#btn')
    function debounce(fn, num) {
      let timeOutId = null
      return function () {
        clearTimeout(timeOutId)
        timeOutId = setTimeout(() => {
          fn.apply(this, arguments)
        }, num)
      }
    }

    function clickFun(e) {
      console.log(2222,e);
    }
    btn.addEventListener('click', debounce(clickFun, 1000))
</script>
Listen for page scrolling events

apply accepts that the first parameter is a dropped object, and the second parameter is an array.

function debounce(cb, delay, ...args) {
  let timer = null
  return function (e) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      cb.apply(this, [e, ...args])
    }, delay)
  }
}

function windowScroll(e, otherParam) {
  console.log('Page scrolling', e, otherParam);
}
// Add page scroll event
window.onscroll = debounce(windowScroll, 500, 'otherParam')

Throttling function

  1. When a high-frequency event is triggered, it is only executed once in n seconds, so throttling will dilute the execution frequency of the function
  2. Each time an event is triggered, judge whether there is a delay function waiting to be executed
Listen for page scrolling events

Declare a canRun judgment, but there is a delayed execution method. If there is, return. If not, use setTimeout to add a delayed execution callback function

function throttle(cb, delay, ...args) {
    let canRun = true
    return function (e) {
      if (!canRun) return
      canRun = false
      setTimeout(() => {
        cb.apply(this, [e, args])
        canRun = true
      }, delay)
    }
}
function windowScroll(e, otherParam) {
    console.log('Page scrolling', e, otherParam);
}

window.onscroll = throttle(windowScroll, 1000, 'otherParam')

One trick is not to declare more than one canRun variable. Use an id returned by setTimeout to assign the id to the timer to judge whether the timer is executed

  function windowScroll(e, otherParam) {
    console.log('Page scrolling', e, otherParam);
  }

  function throttle(cb, delay, ...args) {
    let timer = null
    return (e) => {
      if (!timer) {
        timer = setTimeout(() => {
          // Pass this and Event parameters to the callback
          cb.apply(this, [e, ...args])
          clearTimeout(timer)
          timer = null
        }, delay)
      }
    }
  }
  window.onscroll = throttle(windowScroll, 1000, 'otherParam')

Anti chattering throttling function in Lodash

Lodash: https://www.lodashjs.com/docs/lodash.debounce#_debouncefunc-wait0-options

func (Function): the function to prevent jitter.

[wait=0] (number): the number of milliseconds to delay.

[options=] (Object): option object.

[options.leading=false] (boolean): Specifies the call before the start of the delay.

[options.maxWait] (number): sets the maximum value that func is allowed to delay.

[options.trailing=true] (boolean): Specifies the call after the end of the delay.

Realization of anti shake function

File implementation path: node_modules\lodash\debounce.js

function debounce(func, wait, options) {
   var lastArgs, // Parameters passed by the calling function
      lastThis,  // this of the calling function
      maxWait,  // Maximum waiting time
      result,   // Execution result of the anti shake function
      timerId,   // id of setTimeout
      lastCallTime,  // Last call time
      lastInvokeTime = 0, // Last call time
      leading = false,
      maxing = false,
      trailing = true;
    
    // func determines whether it is a function
    if (typeof func != 'function')
    
    // Change wait to Number type
        
    // If it is an object, the content of the object is assigned to the private attribute
      leading = !!options.leading;
      trailing = 'trailing' in options ? !!options.trailing : false;
    
    // Save current time
    var time = now(),
    
    // shouldInvoke method to judge whether the callback function should be executed
       1, Should be called the first time
          lastCallTime === undefined
       2, 1st + n On the first call
       	 a: The delay time has elapsed. You should call:
           time - lastCallTime >= wait
    	 b: In the source code, it is called when the current time is smaller than the last call time, but is this common:
           time - lastCallTime < 0	    
         c: If there is a maximum delay time, the difference between the current time and the last call time shall be greater than the maximum delay time: 
           (maxing && time - lastInvokeTime >= maxWait))
    
    // Cache the current this and arguments
    lastArgs = arguments;
    lastThis = this;
    
    // The last execution time is assigned as the current time     
    lastCallTime = time;
    
    // Call function
    if(shouldInvoke method)
        // After calling the function
        result = func.apply(thisArg, args);
         
    	// Reset this and arguments 
        lastArgs = lastThis = undefined;
    	
    	// Return structure
    	return result
}
Realization of throttling function

File implementation path: node_modules\lodash\throttle.js

This is all the code of lodash's throttling function. I was confused when I saw the implementation source code of lodash. Can I think debounce is no different from throttle?

import { debounce } './debounce'

function throttle(func, wait, options) {
  var leading = true, 
      trailing = true;

  if (typeof func != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  if (isObject(options)) {
    leading = 'leading' in options ? !!options.leading : leading;
    trailing = 'trailing' in options ? !!options.trailing : trailing;
  }
  return debounce(func, wait, {
    'leading': leading,
    'maxWait': wait,
    'trailing': trailing
  });
}

Difference between anti shake and throttling

You can analyze the statement of the anti chattering throttling function in lodash

debounced lodash

Create a debounced (anti shake) function, which will be called wait after delay of wait milliseconds after the last call. Debounced provides an options object that determines how to call the func method, options Leading and | or options Trailing decides how to trigger before and after the delay (Note: first call, wait or wait first, then call).

When func is called, the last parameter supplied to the debounced function is passed in. The debounced function of subsequent calls returns the result of the last func call

**Summary: * * within a certain period of time, the result obtained is the execution result of the last callback call

throttle lodash

Create a throttling function that executes func at most once in a wait second. This function provides a cancel method to cancel the delayed function call and an immediate call to the flush method. You can provide an options object to determine how to call the func method, options Leading and | or options Trailing determines how to trigger before and after the wait. Func will pass in the last parameter to this function.

The function returned is the result of the last func call.

**Summary: * * within a certain period of time, the result obtained is the execution result of the last callback call

Now I have a big question mark??????????

From lodash's documentation and code, it seems that there is no difference between the release

I began to think about the following two codes carefully, and finally I found a different place,

  1. Callback function called

    debounce if it keeps triggering, the callback function will not be executed, and the last one will be cleared next time (the last one is emphasized)

    If the throttle is triggered all the time, it will only put the callback function for the first time into the personal leave queue (the first time is emphasized)

  2. Effect of call

    debounce if it keeps triggering, the callback function will not execute

    If the throttle is triggered all the time, it will be triggered every delay milliseconds

  3. Same place

    1. All are implemented through setTimeout
    2. It should be executed after delay milliseconds
function debounce(cb, delay, ...args) {
  let timer = null
  return function (e) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      cb.apply(this, [e, ...args])
    }, delay)
  }
}
  function throttle(cb, delay, ...args) {
    let timer = null
    return (e) => {
      if (!timer) {
        timer = setTimeout(() => {
          // Pass this and Event parameters to the callback
          cb.apply(this, [e, ...args])
          clearTimeout(timer)
          timer = null
        }, delay)
      }
    }
  }

What's the difference between these two functions? Please let me know if you know

Keywords: Javascript Front-end

Added by mafkeesxxx on Sat, 08 Jan 2022 18:45:38 +0200