用个小Demo理解防抖与节流

220 阅读2分钟

防抖

指触发事件后在n秒内函数只执行一次,若在n秒内再次触发,则重新计算

例如点击按钮,两秒内触发点击函数,但是你在第1.5秒时又点了一下,这时,函数触发时间重新计算;又如下拉触底加载下一页的功能

<div id="content" style="height: 150px; line-height: 150px; text-align: center; background-color:gray;color: #fff; font-size: 50px; "></div>

<script>
    let num = 1;
    let content = document.getElementById("content");

    function count() {
        content.innerHTML = num++;
    }
    content.onmousemove = count;
</script>

    // 防抖 debounce
    // 让输入完毕后过2秒再查询(延迟执行)
    function debounce(func, wait) {
        let timeout; // 定时器
        return function() {
            if (timeout) clearTimeout(timeout); // 取消之前的任务
            timeout = setTimeout(function() {
                func.apply(this); // this是作用域,指向当前对象,当前对象又是window,因为是全局函数
                // apply是执行func函数
            }, wait)
        }
    }
    content.onmousemove = debounce(count, 2000);
        // 让输入完毕立即查询,但是过2秒后才能再次查询(立即执行)
        function debounce(func, wait) {
            let timeout;
            return function() {
                if (timeout) clearTimeout(timeout);
                let callNow = !timeout; // 类型转换
                timeout = setTimeout(() => { // 增加一个定时器
                    timeout = null; // 清空当前定时器句柄
                }, wait);
                if (callNow) func.apply(this); // 第一次执行
            }
        }
        content.onmousemove = debounce(count, 2000);

节流

指连续发生的事件在n秒内只执行一次函数

如搜索、即时查询功能,当查询数据量太大时,一定要在一定时间内限制查询次数,能减少后端请求压力

        // 节流 throttle 
        // 两种 
        // 定时器方式,固定的时间发请求
        function throttle(func, wait) {
            let timeout; // 定义一个定时器句柄
            return function() {
                if (!timeout) { // 是否存在定时器
                    timeout = setTimeout(() => { // 创建一个定时器
                        timeout = null;
                        func.apply(this); // func==count  apply调用count
                    }, wait);
                }
            }
        }
        content.onmousemove = throttle(count, 2000);
        // 时间戳的方式  移动端多用这种时间戳方式,提高性能
        // 鼠标不管怎么移动,不断触发函数,都是2秒发送一次请求,没有发送多于请求
        function throttle(func, wait) {
            let prev = 0; // 上次记录时间
            return function() {
                let now = Date.now(); // 当前时间
                if (now - prev > wait) { // 当前时间-上次时间>等待时间
                    func.apply(this); // 执行函数  发送请求
                    prev = now; // 重置上次记录时间
                }
            }
        }
        content.onmousemove = throttle(count, 2000);

最后

在学习过程中,代码写的比较乱,我自己看也许会感觉比较清晰,但是读者看着就会稍有迷糊,建议结合自身的学习资料和笔记对照着来看。

本人才疏学浅,文笔拙劣,如有不足之处,还请大家指正。