10分钟教你撸一个节流和防抖函数

222 阅读2分钟

防抖 (debounce)

防抖,顾名思义,防止抖动,以避免在一定时间内多次执行同一事件。

创建一个防抖函数,该函数会从上一次被调用后,延迟 wait 毫秒后调用 func 方法。

  1. 首先,我们为该函数取名( debounce),传递两个参数:第一个参数是实际需要执行的函数(func),第二个参数是等待的时间(wait)。
function debounce(func, wait) {}
  1. 延迟 wait 毫秒调用 func 方法
function debounce(func, wait) {
    return setTimeout(func, wait || 1000)
}
  1. 这一步最关键,在 wait 毫秒内再次调用该函数,那么会取消上一次的调用并且重新延迟 wait 毫秒后调用 func 方法。这里取消上一次调用和重新延迟调用,就很容易想到 setTimeout 和 clearTimeout 两个方法。下面我们来看下如何实现吧
function debounce(func, wait) {
    var timer
    return function() {
        clearTimeout(timer)
        setTimeout(func, wait || 1000)
    }
}

节流(throttle)

节流,顾名思义,节省流量。控制事件发生的频率,如控制为1s发生一次,甚至1分钟发生一次。

创建一个节流函数,在 wait 秒内最多执行 func 一次的函数。

  1. 首先,我们为该函数取名( throttle),传递两个参数:第一个参数是实际需要执行的函数(func),第二个参数是等待的时间(wait)。
function throttle(func, wait) {}
  1. 延迟 wait 毫秒调用 func 方法
function throttle(func, wait) {
    return setTimeout(func, wait || 1000)
}
  1. 这一步最关键,在 wait 毫秒内再次调用该函数,那么会视为无效操作,不再执行。这里视为无效操作,不再执行,就很容易想到创建一个变量,以该变量的布尔值去判断是否执行 func 函数。下面我们来看下如何实现吧
function throttle(func, wait) {
    var canrun = true
    return function() {
        if (!canrun) return
        canrun = false
        setTimeout(() => {
            func()
            canrun = true
        }, wait || 1000)
    }
}
function throttle(cb, wait) {
  var timer
  return function() {
    if (timer) return
    timer = setTimeout(() => {
      cb()
      timer = null
    }, wait || 1000)
  }
}

小结

防抖函数应用场景:

  • 按钮点击太快,以至于多次执行函数
  • 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多
  • 文本编辑器实时保存,当无任何更改操作一秒后进行保存

节流函数应用场景

  • scroll 事件,每隔一秒计算一次位置信息等
  • 浏览器播放事件,每个一秒计算一次进度信息等