1. Why is function anti-shake and function throttling needed?

  • Some calculations and processes are much more expensive than others in the browser. For example,DOMOperation over nonDOMInteractions require more memory and CPU time. Successive attempts to carry on too muchDOMThe operation may cause the browser to hang or even crash.
  • For example, when resizing a browser,resizeEvents fire consecutively; If theresizeAn internal event handler attempt is madeDOMOperation, whose frequent changes may crash the browser;
  • To get around the above problem, you need to throttle this class of functions;

2. What are function stabilization and function throttling

Debounce and throttle are similar but different techniques for controlling how many times a function is executed in a given period of time. The basic idea behind this is that some code cannot be executed continuously and repeatedly without interruption.

2.1 Function anti-shake (debounce)

If an event is triggered more than once frequently and at too short a time interval, the anti-shake function can cause the corresponding event handler to execute only the last time it is triggered. Function stabilization can combine multiple sequential calls into one.

2.2 Function throttling (throttle)

If an event is frequently fired multiple times, the throttling function can perform the corresponding event handling method at a fixed frequency. Function throttling ensures that an event is executed only once in a given period of time.

3. Application scenarios

type scenario
Function image stabilization 1. Mobile phone number and email input detection

2. The search box searches for input (just relax the Ajax request after the last input)

3. Window sizeresize(Only after the window adjustment is complete, calculate the window size to prevent repeated rendering)

4. Rolling eventsscroll(Handlers that simply execute the last scrolling event that was triggered)

5. Verification of text input (Send AJAX request for verification after continuous text input, verify once (after stopping input)
Function of the throttle 1. DOMElement drag-and-drop implementation (mousemove)

2. Shootersmousedown/keydownEvents (only one bullet per unit of time)

3. Calculate the distance of mouse movement (mousemove)

4. Search association (keyup)

5. Rolling eventsscroll, (As long as the page scroll will be judged at an interval of time)

4. How

4.1 Function anti-shake implementation

function debounce(fn, delay, scope) {
    lettimer = null; // The return function forms a closure for the debounce scopereturn function () {
        // setThe function environment used in Timeout() is always window, so a copy of the current environment is required;letcontext = scope || this, args = arguments; // If the event is triggered, clear the timer and restart the timer clearTimeout(timer); timer =setTimeout(function() { fn.apply(context, args); }, delay); }}Copy the code
  • Code reading
  1. The first time the function is called, a timer is created that runs the code after a specified interval;
  2. When the function is called a second time, it clears the previous timer and sets another;
  3. If the previous timer has already been executed, this operation is meaningless;
  4. However, if the previous timer is not executed, it is simply replaced with a new timer;
  5. The goal is to execute only after the request to execute the function has stopped the delay time.

4.2 Function throttling implementation

4.2.1 Simple implementation with timestamp

function throttle(fn, threshold, scope) {
    let timer;
    let prev = Date.now();
    return function () {
        let context = scope || this, args = arguments;
        let now = Date.now();
        if(now - prev > threshold) { prev = now; fn.apply(context, args); }}}Copy the code

4.2.2 Simple implementation using timer

function throttle2(fn, threshold, scope) {
    let timer;
    return function () {
        let context = scope || this, args = arguments;
        if(! timer) { timer =setTimeout(function () {
                fn.apply(context, args);
                timer = null;
            }, threshold)
        }
    }
}
Copy the code

5, for example (scrollEvents)

CSS code

    .wrap {
       width: 200px;
        height: 330px;
        margin: 50px;
        margin-top: 200px;
        position: relative;
        float: left;
        background-color: yellow;
    }
    .header{
        width: 100%;
        height: 30px;
        background-color: #a8d4f4;
        text-align: center;
        line-height: 30px;
    }
    .container {
        background-color: pink;
        box-sizing: content-box;
        width: 200px;
        height: 300px;
        overflow: scroll;
        position: relative;
    }
    .content {
        width: 140px;
        height: 800px;
        margin: auto;
        background-color: #14ffb2;
    }
Copy the code

The HTML code

    <div class="wrap">
        <div class="header"> scroll events: normal </div> <div class="container">
            <div class="content"></div>
        </div>
    </div>
    <div class="wrap">
        <div class="header"</strong></div> <div class="container">
            <div class="content"></div>
        </div>
    </div>
    <div class="wrap">
        <div class="header"</strong></div> <div class="container">
            <div class="content"></div>
        </div>
    </div>
Copy the code

JS code

    let els = document.getElementsByClassName('container');
    let count1 = 0,count2 = 0,count3 = 0;
    const THRESHOLD = 200;

    els[0].addEventListener('scroll'.function handle() {
        console.log('Normal scrolling event! count1=', ++count1);
    });
    els[1].addEventListener('scroll', debounce(function handle() {
        console.log('Perform the scroll event! Count2 =', ++count2);
    }, THRESHOLD));
    els[2].addEventListener('scroll', throttle(function handle() {
        console.log(Date.now(),', perform the scroll event! (Function throttling) count3=', ++count3);
    }, THRESHOLD));
Copy the code
// Function buffetingfunction debounce(fn, delay, scope) {
    let timer = null;
    let count = 1;
    return function () {
        let context = scope || this,
            args = arguments;
        clearTimeout(timer);
        console.log(Date.now(), ", trigger", count++, "Second rolling event!");
        timer = setTimeout(function () {
            fn.apply(context, args);
            console.log(Date.now(), The timeout call triggered by the last event can only be executed after the delay time if the high frequency event stops!); }, delay); }}Copy the code
// function throttlingfunction throttle(fn, threshold, scope) {
    let timer;
    let prev = Date.now();
    return function () {
        let context = scope || this, args = arguments;
        let now = Date.now();
        if(now - prev > threshold) { prev = now; fn.apply(context, args); }}}Copy the code

Presentation and comparison of execution results

6. Summary

  • debounceandthrottleBoth methods improve the performance of event handlers by reducing the execution of actual event handlers that trigger events at high frequencies, without substantially reducing the number of events that trigger.
  • Debounce can combine multiple sequential calls into one.
  • throttleEnsure that an event is executed only once in a specified period of time.