防抖&节流学习 - 1 | 青训营笔记

69 阅读2分钟

Debounce

首先先聊聊防抖吧

  1. 定义:

    把多次请求合并成一个请求,这多个请求其实都会被调用,但只有其中的一个会被完整地正确地执行。

  2. 当然你可能会想问被合成地这一个请求,它出现的时间点是什么?

    分为两种情况:

    • (Leading options) 出现在第一个请求,然后后面的请求就会被合成为这一个请求
    • (Trailing options) 出现在最后一个请求后的一段时间,就是之前的所有的请求都会被合成为这一个请求
    • (注意这里的后的一段时间,只有 Trailing Options 有这个限制,Leading Options 没有这个限制 )
  3. 那它一般是有什么运用场景捏

    一般是在用在处理短时间多次触发的 (代价较大的 如时间和资源消耗较大的 等等) 操作上,如:

    • 短时间内多次按钮点击,而只想该按钮触发一次,如某个按钮点击后会发起一个请求,而设计时想节省和保护服务器资源,就会将短时间多次触发的请求合成为一个
    • 还有比如说,输入自动补全或者是提示,只有当输入停止时才会触发,而当持续输入时则不会被触发
  4. 那最简单,最基本的实现方法是什么捏?

    下面展示的 Trailing Options的实现方式⬇️:

    const debounce = (fn, delay) => {
        let timeoutId;
        
        return function(...args) {
            if(timeoutId) {
                clearTimeout(timeoutId);
            }
            timeoutId = setTimeout(() => {
                fn(...args);
            }, delay)
        }
    }
    
    • 首先看下最外层

      debounce 这个箭头函数接受两个参数 一个是 fn 即想要被 debounce 化的函数; 还有一个是delay 可以理解为 上文第二点 中提到的 后的一段时间,或者可以理解为超出这段时间的再次调用,不会参与到和上次调用相关的合并中去。

    • 然后再看下内层

      这里是使用闭包,使得被返回的函数记住timeoutId这个变量。

    • 然后看下被返回的函数

      是在原本要调用的函数外再加一层,首先对timeoutId进行刷新,其实就是将之前的setTimeout清除,重新设置一个timeout大于delaydebouce传进来的第二个参数)。

    • 通过这些操作,我们就得到了debounce函数,经过它的处理,连续的调用实际上都会被合并成一个函数,(这里实现的是Trailing Options型的,所以被合并的调用会出现在连续调用的最后一次调用的一段时间后 即传入的delay值)。