Function anti-shake and function throttling in js

1. What are function anti-shake and function throttling?

    Both anti-shake ( debounce) and throttling ( throttle) are techniques used to control how many times a function is executed within a certain period of time. The two are similar and different. The basic idea is that certain codes cannot be repeated continuously without interruption implement

1.1 Function anti-shake

If an event is frequently executed multiple times and the trigger interval is too short, the anti-shake function can make the corresponding event processing function only execute the last triggered one. Function anti-shake can combine multiple sequential calls into one.

1.2 Function throttling

If an event is frequently triggered multiple times, the throttling function can execute the corresponding event processing method at a fixed frequency. Function throttling ensures that an event can only be executed once within a certain event.

2. Application

type Scenes
1. Input in the search box (only need to relax the Ajax request after the last input is completed)
Function anti-shake 2. Scroll event scroll(only need to execute the handler of the last scroll event after triggering)
3. Verification of text input (send Ajax request for verification after continuous text input, and verify once after stopping input)
1. DOMImplement the drag and drop function of elements ( mousemove)
function throttling 2. Refresh rate in the game
3. CanvasBrush function

In general, the function anti-shake is suitable for multiple events and one response, and the function throttling is suitable for a large number of events to be evenly distributed and triggered according to time.

3. Realize

  3.1 Realize function anti-shake

function debounce(fn, wait) {
    
    
  var timer = null;
    // 返回函数对debounce作用域形成闭包
  return function () {
    
    
      var context = this
      var args = arguments
      if (timer) {
    
    
          // 事件被触发,清除timer并重新开始计时
          clearTimeout(timer);
          timer = null;
      }
      timer = setTimeout(function () {
    
    
          fn.apply(context, args)
      }, wait)
  }
}

var fn = function () {
    
    
  console.log('boom')
}

setInterval(debounce(fn,500),1000) // 第一次在1500ms后触发,之后每1000ms触发一次

setInterval(debounce(fn,2000),1000) // 不会触发一次(把函数防抖看出技能读条,如果读条没完成就用技能,便会失败而且重新读条)

1. Create a timer when calling the function for the first time, and run the code after the specified time

2. When the function is called for the second time, the previous timer will be cleared and another one will be set

3. If the previous timer has already been executed, this operation has no meaning

4. When the previous timer is not executed, replace it with a new timer

5. The purpose is to waitexecute only after the request to execute the function has stopped for time

  3.2 Realize function throttling

    1) Using timestamp to achieve

// fn 是需要执行的函数
// wait 是时间间隔
const throttle = (fn, wait = 50) => {
    
    
  // 上一次执行 fn 的时间
  let previous = 0
  // 将 throttle 处理结果当作函数返回
  return function(...args) {
    
    
    // 获取当前时间,转换成时间戳,单位毫秒
    let now = +new Date()
    // 将当前时间和上一次执行函数的时间进行对比
    // 大于等待时间就把 previous 设置为当前时间并执行函数 fn
    if (now - previous > wait) {
    
    
      previous = now
      fn.apply(this, args)
    }
  }
}

// DEMO
// 执行 throttle 函数返回新函数
const betterFn = throttle(() => console.log('fn 函数执行了'), 1000)
// 每 10 毫秒执行一次 betterFn 函数,但是只有时间差大于 1000 时才会执行 fn
setInterval(betterFn, 10)

    2) Realized by using timer

function throttle(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)
        }
    }
}

4. Instance ( scrollevent)

     <!-- CSS样式 -->
    <style>
        .wrap {
      
      
            width: 200px;
            height: 330px;
            margin: 50px;
            margin-top: 200px;
            position: relative;
            float: left;
        }

        .header {
      
      
            width: 100%;
            height: 30px;
            background-color: #a8d4f4;
            text-align: center;
            line-height: 30px;
        }

        .container {
      
      
            background-color: darkseagreen;
            box-sizing: content-box;
            width: 200px;
            height: 300px;
            overflow: scroll;
            position: relative;
        }

        .content {
      
      
            width: 140px;
            height: 800px;
            margin: auto;
            background-color: cadetblue;
        }
    </style>

<!-- html -->
<body>
    <div class="wrap">
        <div class="header">滚动事件:普通</div>
        <div class="container">
            <div class="content"></div>
        </div>
    </div>
    <div class="wrap">
        <div class="header">滚动事件:<strong>加了函数防抖</strong></div>
        <div class="container">
            <div class="content"></div>
        </div>
    </div>
    <div class="wrap">
        <div class="header">滚动事件:<strong>加了函数节流</strong></div>
        <div class="container">
            <div class="content"></div>
        </div>
    </div>
</body>
 let els = document.getElementsByClassName('container');
        let count1 = 0,
            count2 = 0,
            count3 = 0;
        const THRESHOLD = 200;

        els[0].addEventListener('scroll', function handle() {
    
    
            console.log('普通滚动事件!count1=', ++count1);
        });
        els[1].addEventListener('scroll', debounce(function handle() {
    
    
            console.log('执行滚动事件!(函数防抖) count2=', ++count2);
        }, THRESHOLD));
        els[2].addEventListener('scroll', throttle(function handle() {
    
    
            console.log(Date.now(), ', 执行滚动事件!(函数节流) count3=', ++count3);
        }, THRESHOLD));

        // 函数防抖
        function debounce(fn, delay, scope) {
    
    
            let timer = null;
            let count = 1;
            return function () {
    
    
                let context = scope || this,
                    args = arguments;
                clearTimeout(timer);
                console.log(Date.now(), ", 触发第", count++, "次滚动事件!");
                timer = setTimeout(function () {
    
    
                    fn.apply(context, args);
                    console.log(Date.now(), ", 可见只有当高频事件停止,最后一次事件触发的超时调用才能在delay时间后执行!");
                }, delay);
            }
        }

        // 函数节流
        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);
                }
            }
        }

operation result:
![Normal](https://img-blog.csdnimg.cn/77feb83f70014316a59cb0ee46ace82c.png#pic_center

Function anti-shake
insert image description here

Guess you like

Origin blog.csdn.net/m0_52900946/article/details/124778757