函数防抖、函数节流

1、事件频繁触发可能造成的问题?

  (1)、一些浏览器事件: window.onresize、window.onmousemove等,触发的频率非常高,会造成浏览器性能问题。

  (2)、如果向后台发送请求,频繁触发,对服务器造成不必要的压力;例如百度搜索时输入字符,每改变一下输入框字符时就去请求一下,如果不处理就会产生不必要的多余请求,给服务器产生压力。

2、如何限制事件处理函数的频繁调用

  主要在于函数调用函数执行之间的处理

  (1)、函数节流

  (2)、函数防抖

3、函数节流(throttle)

  (1)、理解:

    一个函数频繁触发调用,在一定时间T周期内只执行一次调用,实现原理有两种:

    (a)、在一定时间T周期的最开始调用,立即执行:在一个函数频繁触发调用时,第一次调用函数立即执行,在往后规定时间T内再次调用该函数不再执行,直到规定时间T后再次调用函数理解执行,周期循环这一过程。

    (b)、在一定时间T周期的最开始调用,经过时间T后执行:在一个函数频繁触发调用时,第一次调用函数使用计时器,当计时器经过一定时间T再执行函数,在这一定时间T内其他的函数不予执行。周期循环这一过程。

    适合与多次事件按时间平价分配触发。

  (2)、应用场景

    窗口调整(onresize)

    页面滚动(onscroll)

    DOM元素拖拽(onmousemove)

    抢购疯狂点击(onclick)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>throttle与debounce</title>
</head>
<body>
    <div>
        <button>(时间戳)节流函数</button>
        <button>(计时器)防抖函数</button>
    </div>
</body>
<script>
window.onload = function () {
    // 以时间戳来实现返回节流函数的工具函数
    function timeStampThrottle(callback, delay = 1000) {
        let pre = 0; //设置初始调用时间为0
        return function (event) {
            const current = Date.now(); // 获取当前调用时间
            if (current - pre > delay) {  // 只用离上次调用callback的时间大于delay时才再次调用callback
                callback.call(this, event) // 调用真正处理事件的函数,this作为事件源,参数是event
                // 记录此次调用的时间
                pre = current
            }
        }
    };
    // 以计时器来实现返回节流函数的工具函数
    function timeMeterThrottle(callback, delay = 1000) {
        let timer = null;
        return function (event) {
            if (!timer) {
                timer = setTimeout(() => {
                    callback.call(this, event)
                    timer = null;
                }, delay)
            }
        }
    };
    function handleClick() {
        console.log("执行了函数", this, event);
    };
    document.getElementsByTagName("button")[0].onclick = timeStampThrottle(handleClick, 2000);
    document.getElementsByTagName("button")[1].onclick = timeMeterThrottle(handleClick, 2000);
}
</script>
</html>

4、函数防抖(debounce)

  (1)、理解:

    在一个函数频繁触发调用时,其中函数A调用后执行的条件是下一次函数B调用与函数A调用时间间隔大于规定时间T,且函数A执行的时间为函数A调用时的时间+规定时间T。

    适合多次事件一个响应的情况

  (2)、场景:

    输入框实时搜索联想(keyup/input)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>debounce函数防抖</title>
</head>

<body>
    <div>
        <button>函数防抖</button>
    </div>
</body>
<script>
    window.onload = function () {
        function debounce(callback, delay) {
            return function (event) {
                // 如果上次事件还没有真正执行完成,取消它
                if (callback.hasOwnProperty("timeoutId")) {
                    clearTimeout(callback.timeoutId)
                };
                // 启动定时器,在delay时间后执行
                callback.timeoutId = setTimeout(() => {
                    // 正在执行事件
                    callback.call(this, event);
                    // 删除准备执行的标记
                    delete callback.timeoutId;
                }, delay);
            }
        };
        function handleClick() {
            console.log("执行了函数", this, event);
        };
        document.getElementsByTagName("button")[0].onclick = debounce(handleClick, 2000);
    }
</script>

</html>

 

posted @ 2021-01-31 16:23  只争朝夕,不负韶华  阅读(190)  评论(0编辑  收藏  举报