throttle简单实现

646 阅读2分钟

这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战

是什么?

节流的原理是,我们给定一个时间(n),在这个时间(n)内,无论我们怎么触发,他都只会执行一次,等这个时间过去了,我们才会进行第二次执行,然后再等n秒,再进行第三次执行。。。一直这样下去

为什么?

在日常业务开发中,会有很多频繁触发的事件,如果我们不对他们做一些处理,会有很大的性能问题。处理不当或者放任不管就容易引起浏览器卡死。
我们应该都有做过这样的需求,监听页面的滚动事件,滚动到一定的地方,顶部的tab栏的高亮会跟着定位改变,如果使用防抖来处理频繁触发事件的话,如果用户一直滚动,不停,那么tab栏的高亮永远不会做出反应,这个时候我们就可以使用节流来处理了,一定时间内就算用户一直在触发事件,我们也给他做出响应,高亮对应tab

怎么用

简单实现 我创建了一个box,然后在这个box上进行了mousemove事件,每次触发事件都对value值进行增加

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            margin-top: 100px;
            display: flex;
            justify-content: center;
            background: #BFA2DB;
        }

        #div1 {
            display: flex;
            justify-content: center;
            align-items: center;
            width: 200px;
            height: 200px;
            color: #7F7C82;
            background-color: #F3F1F5;
        }
    </style>
</head>

<body>
    <div id="div1"></div>
    <script>
        var value = 1;
        var div1 = document.getElementById('div1');
        function count() {
            div1.innerHTML = value++;
        };
        div1.onmousemove = count;
    </script>
</body>

</html>

1.gif

可以看到,一直在移动。根据上面是什么的描述,我们可以根据时间戳去实现这个节流的简单函数

div1.onmousemove = throttle(count,3000);
function throttle(fn, wait) {
    let prev = 0
    return (...args) => {
        let now = +new Date()
        if (now - prev > wait) {
            fn.apply(this, args)
            prev = now
        }
    }
}

2.gif

现在,我给他设置了3s内只执行一次,可以看到,我在上面一直触发事件,但他每三秒才会执行一次。

我们也可以使用定时器去实现

div1.onmousemove = throttle(count, 2000);
function throttle(fn, wait) {
    let timer = 0
    return (...args) => {
        if (!timer) {
            timer = setTimeout(function () {
                timer = null;
                fn.apply(this, args)
            }, wait)
        }
    }
}

3.gif

当鼠标移入的时候,事件不会立刻执行,2s后执行了一次,6.2s 的时候停止触发,但是依然会在第 8s 的时候执行一次事件。

之后,还可以对这个函数进行优化,进入就执行,移除事件之后就不再执行。