防抖和节流

防抖

触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间。
例如公交车司机,手里面有一个计时器,如果三分钟之内没有人再上车,他就发车。司机第一次按下了计时器,结果到了一分半钟的时候,有一个乘客上车了,此时他就把手里的计时器清零,然后再等待三分钟,结果又过了两分钟,又上来了一个乘客,司机不得不再次把计时器清零,就一直这么持续下去,直到计时器在三分钟之内没有乘客再上车,那么司机就可以发车了。
实现思路:每次触发事件时都取消之前的延时调用方法。

function debounce(func, delay) {
  let timer // 创建一个标记用来存放定时器的返回值
  return function (...args) {
    if (timer) {
      clearTimeout(timer) //如果用户再次输入,则把前一个 setTimeout clear 掉
    }
    timer = setTimeout(() => {
      func.apply(this, args) //利用apply保证我们的this指向我们调用的那个对象
    }, delay)
    // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 delay 间隔内如果还有字符输入的话,就不会执行 fnnc 函数
  }
}

防抖的应用:防抖最佳的应用就是用在处理用户输入,有个输入框,输入之后会调用接口,获取联想词。但是,因为频繁调用接口不太好,所以我们在代码中使用防抖功能,只有在用户输入完毕的一段时间后,才会调用接口,出现联想词。

节流

高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。
实现思路:每次触发事件时都判断当前是否有等待执行的延时函数

function throttle(func, delay) {
  let canRun = true //通过闭包保存一个标记
  return function (...args) {
    if (!canRun) return //在函数开头判断标志是否为 true,不为 true 则中断函数
    canRun = false //将canRun 设置为 false,防止执行之前再被执行
    setTimeout(() => {
      // 将外部传入的函数的执行放在setTimeout中
      func.apply(this, args)
      // 执行完事件(比如调用完接口)之后,重新将这个标志设置为 true。当定时器没有执行的时候标记永远是false,在开头被return掉
      canRun = true
    }, delay)
  }
}

节流的应用:

  1. 懒加载要监听计算滚动条的位置,使用节流按一定时间的频率获取。
  2. 用户点击提交按钮,假设我们知道接口大致的返回时间的情况下,我们使用节流,只允许一定时间内点击一次。