防抖与节流的理解以及应用场景

191 阅读3分钟

一、防抖

定义:

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, 300));

二、节流

定义:

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("keyup", throttle(handle, 300));

三、区别

相同点:

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

不同点:

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

四、总结:

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

应用场景:

  • 搜索框搜索输入,只需要用户最后一次输入完再发送请求。
  • 窗口大小resize,只需窗口调整完成后,计算窗口大小。防止重复渲染。
  • 在点赞、输入框校验、取消点赞、创建订单等发送网络请求的时候,如果我们连续点击按钮,可能会发送多次请求。这个对于后台来说是不允许的。(涉及到会频繁调用接口的情景下, 延迟时间一般设置300ms)

节流:使得一定时间内只触发一次函数,并且执行的是第一次的函数。

应用场景:

  • 滚动加载,加载更多或滚到底部监听。

  • 搜索框,搜索联想功能。

  • DOM 元素的拖拽功能实现

  • 计算鼠标移动的距离

  • Canvas 模拟画板功能

  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)