likes
comments
collection
share

JavaScript “防抖”和“节流”详解与应用

作者站长头像
站长
· 阅读数 21

在我们日常开发过程中,可能会遇到这样一些情况:当我们频繁点击页面上某个按钮或者鼠标滚轮不停地滚动的时候,会出现页面卡死的问题,用户体验就很不好,为了优化这些问题,我们引入了“防抖”和“节流”。

阅读本文,你将

  1. 知道什么是“防抖”,什么是“节流”;
  2. 了解“防抖”和“节流”各自的实现原理;
  3. 知道“防抖”和“节流”各自的应用场景。

1、防抖

定义:

n秒后再执行该事件,如果在这n秒内被触发了,则重新开始计时。

举个例子:我们每天上下班都会乘电梯,如果把电梯运送当做一个函数,假设电梯超时设定为20秒,不考虑容量限制。

当电梯第一个人进来之后,等待20秒,电梯自动关门运行,如果这个等待的过程中又有人进来了,20秒等待重新计时,直到20秒后关门运行,这个便是防抖。

实现原理:

每次触发事件时设置一个延迟调用方法,并且取消之前的延迟调用方法。

缺点:

如果事件在规定时间间隔内被不断地触发,则调用方法会被不断地延迟。

// 防抖函数
function debounce(fn, delay) {
    let timeout = null;
    return function() {
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            fn.apply(this, arguments);
        }, delay);
    }
}
// 处理函数
function handle() {
    console.log("防抖");
}
// 比如页面滚动事件
window.addEventListener("scroll", debonce(handle, 500));

2、节流

定义:

n秒内只运行一次,若在n秒内被重复触发,只有一次生效。

举个例子:还是乘电梯,电梯门每隔20秒自动关门运行,20秒之内不管你进来几个人,只要20秒时间到了,门就自动关上。

实现原理:

每次触发事件时,如果当前有等待执行的延时函数,则直接return

// 节流函数
function throttle(fn, delay) {
    let flag = true;
    return function() {
        if(!flag) return;
        flag = false;
        setTimeout(() => {
            fn.apply(this, arguments);
            flag = true;
        }, 500)
    }
}
// 处理函数
function handle() {
    console.log("节流");
}
window.addEventListener("resize", throttle(handle, 500));

总结:

防抖:将多次操作合并为一次操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置,这样一来,只有最后一次操作能被触发。

应用场景:

  • 搜索框搜索输入,只需要用户最后一次输入完再发送请求。
  • 窗口大小resize,只需窗口调整完成后,计算窗口大小。防止重复渲染。

节流:使得一定时间内只触发一次函数。

应用场景:

  • 滚动加载,加载更多或滚到底部监听。
  • 搜索框,搜索联想功能。

区别:

相同点:

  • 都可以通过使用setTimeout实现
  • 目的都是降低回调执行频率,节省计算资源。

不同点:

节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而防抖只是在最后一次事件后才触发一次函数。