前端基本功(九):彻底理解函数节流与防抖,以及我是如何在日常开发中应用函数节流与防抖的。

2,540 阅读3分钟

1. 如何理解函数节流与函数防抖

  1. 函数节流(throttle):从字面上理解,就是节约函数的执行次数(约定一定的时间执行一次),在我们进行一些高频执行函数的操作中可以应用。
  2. 函数防抖(debounce):从字面上理解,防止函数抖动,那么函数为什么会抖动?就是在我们还没有完全确认此刻操作的时候频繁执行函数,防抖就是合并我们的函数执行(多个欲执行函数到约定的时间点后再合并执行)。只有触发操作后超过指定的间隔说明这一次触发才有效,否则就要重新计时等待。

2. 手动实现节流与防抖

1. 函数节流
  1. 实现思路:利用定时器在第一次触发函数时打一个开关,代表我已经进入了倒计时,在指定的时间后会触发,但是你在这个指定的时间之前都通过判断这个开关是打开状态就无法再次触发函数,等到倒计时结束开关关闭,下次执行就可以再次进行倒计时操作。也就实现了约定一定的时间执行一次函数的操作。

  2. 简单代码实现:

    function throttle(fn, delay = 500) {
      let canRun = true; 
      return function() {
        // 这里其实是使用了闭包的原理,函数内部保存使用了函数外部的变量。
        if(!canRun) return;
        canRun = false;
        setTimeout(() => {
          fn.apply(this, arguments);
          canRun = true;
        }, delay)
      }
    }
    
2. 函数防抖
  1. 实现思路:还是同样需要利用定时器,当我们执行这个函数时,会生成一个定时器,但是如果你重复执行这个函数,每次执行函数的第一步是清除上一次的定时器,这样就可以达成只有触发操作后超过指定的间隔说明这一次触发才有效,否则就要重新计时等待。

  2. 简单代码实现:

    function debounce(fn, delay = 500) {
      let timeout = null;
      return function() {
        clearTimeout(timeout);
        timeout = setTimeout(() => {
          fn.apply(this, arguments);
        }, delay)
      }
    }
    

3. 我在开发中使用的案例

  1. 一般情况下,我们在日常开发中都会使用一些函数库比如说loadsh、underscore等。这些类库一般都已经封装好了throttle、debounce等函数,我们一般直接使用即可。
  2. 前段时间产品就提出了一个需求:我们只需要在一个输入框中输入一个客户的关键字,就可以模糊筛选中匹配指定的客户。如果说,我们只要监听onchange事件就请求后台接口匹配的数据即可。但是这样导致的问题是,用户仅仅还在输入法联想阶段或者是正在输入状态下,也会到此请求接口。那么这种情景下就可以使用我们debounce函数来进行优化。
// 案例一:这里使用了装饰器包装了loadsh中的debounce
  @Debounce(300)
  onSearch(name) {
    this.props.dispatch({type: 'sysUser/queryOrgUser', payload: {
      body: {
        name,
        role: USERROLE_TYPE.ACCOUNT_MANAGEMENT,
      }
    }});
  }

// 案例二:这里直接用的loadsh的debounce包装了我们方法
  const debounceCalculate = debounce(this.trialTranslateMoney, 500);
  if(value <= num) {
    debounceCalculate({
      investAmt: value
    })
  }else {
    this.money = num;
  }