Home  >  Article  >  Web Front-end  >  JavaScript topic three: anti-shake

JavaScript topic three: anti-shake

coldplay.xixi
coldplay.xixiforward
2021-03-04 09:56:003175browse

JavaScript topic three: anti-shake

Contents

  • 1. Why anti-shake is needed
  • 2. Anti-shake Principle
  • 3. Simple implementation of anti-shake
  • 4. Advanced anti-shake
  • Write at the end

(Related free learning recommendations: javascript video tutorial)

1. Why is anti-shake required

  • High-frequency function operations may have adverse effects
  • Such as: resize, scroll, mousedown, mousemove, keyup, keydown...

To this end, we give a sample code to understand how the event is triggered frequently:

We write an index.html file:

    <meta>
    <meta>
    <meta>
    <title>Document</title>
    <title>debounce</title>
    <style>
        #wrapper {
            width: 100%;
            height: 200px;
            line-height: 200px;
            text-align: center;
            color: #fff;
            background-color: #444;
            font-size: 30px;
        }
    </style>
    <p></p>
    <script>
        var count = 1;
        var op = document.getElementById("wrapper");

        function getUserAction() {
            op.innerHTML = count++;
        }

        op.onmousemove = getUserAction;
    </script>

It triggers nearly 100 times when sliding from the left to the right getUserAction Function! Look at the following Gif:

JavaScript topic three: anti-shake

Because this example is very simple, the browser can fully respond, but suppose:

  • It is triggered extremely frequently High, 2000 times per minute, and involves a lot of position calculation, DOM operations, etc.
  • There are interface requests. The execution time of a single function is long, but the trigger interval of each function is very close.

This kind of interaction that puts too much pressure on the browser or server in an instant (a short period of time) needs to be optimized. In order to solve this problem, there are generally two solutions:

  • debounce anti-shake
  • throttle throttling

Their purpose is: Reduce the triggering frequency of a function to improve performance or avoid Waste of resources.

2. The principle of anti-shake

Today we will focus on the implementation of anti-shake.

The principle of anti-shake is: Even if you trigger an event, I will execute it only after n seconds of inactivity after the event is triggered. For example:

We stipulate

3s as the standard for anti-shake, then:

    The first time an event is requested - the countdown is 3s
  1. at this time
  2. Countdown 2s
  3. Countdown 1s
  4. The event is triggered again at 0.5s - now countdown 3s
  5. ...Nothing happens within 3s
  6. Execute The event took 5.5s

JavaScript topic three: anti-shake

3. Implement an anti-shake by yourself

3.1 First Edition

We implement the first version of the code based on the core ideas mentioned in the previous section:

function debounce(func, wait) {
    var timer;
    return function () {
        clearTimeout(timer)
        timer = setTimeout(func, wait);
    }}
If we want to use it, take the example in the first section as an example:

op.onmousemove = debounce(getUserAction, 2000);
At this time You can test it again. When the event continues to occur, the event will only be triggered after 2 seconds of complete stop:

Written here, as a requirement for some high-frequency events, it is over. Let’s take a look at its effect:

JavaScript topic three: anti-shake

3.2 Second Edition

As we all know, when a dom node triggers an event, this points to itself. In this example, it points to

op, but in this case: Let’s take a look at

var count = 1;var op = document.getElementById("op");function getUserAction() {
    op.innerHTML = count++;
    console.log('this', this); // 此时输出 Window...}op.onmousemove = debounce(getUserAction, 2000);function debounce(func, wait) {
    var timer;
    return function () {
        clearTimeout(timer)
        timer = setTimeout(func, wait);
    }}
. After all, it has been wrapped by a layer of anonymous functions. This already points to window. In order to reduce the impact, we Try to fix it

function debounce(func, wait) {
    var timer;
    return function () {
        var _this = this; // 记录当前this

        clearTimeout(timer)
        timer = setTimeout(function(){
            func.apply(_this); //将 func的this改为_this
        }, wait);
    }}
Third Edition

The this pointing problem solved, our function is still not "perfect" enough, in JavaScript, the event processing function will provide the

event object , we call it e for short.

// 使用了 debouce 函数function getUserAction(e) {
    console.log(e); // undefined
    op.innerHTML = count++;};
In order to ensure its authenticity, we will change the third version:

var count = 1;var op = document.getElementById("op");function getUserAction(e) {
    op.innerHTML = count++;
    console.log('e', e); // MouseEvent}op.onmousemove = debounce(getUserAction, 2000);function debounce(func, wait) {
    var timer;
    return function () {
        var _this = this; // 记录当前this
        var arg = arguments; // 记录参数
        clearTimeout(timer)
        timer = setTimeout(function () {
            func.apply(_this, arg); //将 func的this改为_this
        }, wait);
    }}
So far, we have added to the function while retaining the original capabilities of the Dom event as much as possible. With the anti-shake effect, it can solve most of our daily development anti-shake problems, but we need to be more "perfect"

JavaScript topic three: anti-shake

4. Anti-shake advanced

4.1 Immediate execution

This requirement is:

    Immediate execution
  • Keep
  • n seconds blank period
  • Put
  • n second blank period behind
It makes sense to think about this requirement, then let’s add

immediate The parameter determines whether it is executed immediately.

function debounce(func, wait, immediate) {
    var timer;

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

        if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timer; // 1. callNow 初始值是 true, 同步立即执行;随后 timer 才开始执行
            timer = setTimeout(function(){
                timer = null; // wait 期间,timer 是一个 ID 数字,所以 callNow 为 false,func 在此期间永远不会执行
            }, wait) // wait 之后,timer 赋值 null,callNow 为 true,func 又开始立即执行。
            if (callNow) func.apply(_this, args)
        }
        else {
            timer = setTimeout(function(){
                func.apply(_this, args)
            }, wait);
        }
    }}
Let’s take a look at its effect at this time:

JavaScript topic three: anti-shake

4.2 Add simple verification

function debounce(func, wait, immediate) {
    var timer;
    // 检查函数
    if (typeof func !== 'function') {
        throw new TypeError('Expected a function');
    }
    // 保证wait存在
    wait = +wait || 0;

    const debounced = function () {
        var _this = this;
        var args = arguments;

        if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timer; // 如果不存在定时器,则callNow为true
            timer = setTimeout(function () {
                timer = null; // 为了保证之后的时效性,手动添加timer
            }, wait)
            // 因为不存在timer,证明是首次执行,所以直接调用
            if (callNow) func.apply(_this, args)
        }
        else {
            timer = setTimeout(function () {
                func.apply(_this, args)
            }, wait);
        }
    }
    return debounced}

4.3 Add cancellation event method

If you want to cancel the anti-shake event, we can write like this:

function debounce(func, wait, immediate) {
    var timer;
    // 检查函数
    if (typeof func !== 'function') {
        throw new TypeError('Expected a function');
    }
    // 保证wait存在
    wait = +wait || 0;

    const debounced = function () {
        var _this = this;
        var args = arguments;

        if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timer; // 如果不存在定时器,则callNow为true
            timer = setTimeout(function () {
                timer = null; // 为了保证之后的时效性,手动添加timer
            }, wait)
            // 因为不存在timer,证明是首次执行,所以直接调用
            if (callNow) func.apply(_this, args)
        }
        else {
            timer = setTimeout(function () {
                func.apply(_this, args)
            }, wait);
        }
    }

    const cancel = function(){
        clearTimeout(timer);
        timer = null;
    }

    const pending = function(){
        return timer !== undefined;
    }

    debounced.cancel = cancel;
    debounced.pending = pending;
    return debounced}
Let’s take a look at the effect:

JavaScript topic three: anti-shake

Write Even if this simple anti-shake method is OK, it is indeed not perfect. If you have any suggestions for improvement, please leave a message in the comment area~

Related free learning recommendations: javascript (Video)

The above is the detailed content of JavaScript topic three: anti-shake. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete