Skip to content

Latest commit

 

History

History
128 lines (89 loc) · 4.41 KB

节流和防抖.md

File metadata and controls

128 lines (89 loc) · 4.41 KB

节流和防抖

使用 JavaScript 进行开发时,都会使用到事件,有一些事件我们只想触发一次,但却频繁触发多次,例如:

  • windowresizescroll
  • mousedownmousemove
  • keyupkeydown
  • ...

我们可能会在其中执行请求,或处理一些复杂的逻辑,这样一次性触发多次可能会造成资源浪费。

有两种方法可以控制事件触发后,回调函数的调用频率,即节流和防抖

防抖

防抖(debounce)是指在一段时间内最多调用一次,即如果在规定时间内再次调用该函数,则会将原定时器清除并重新计时。

常规防抖实现如下:

function debounce(fn, wait) {
  let timer = null
  return function () {
    clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, arguments)
    }, wait)
    // 方便在外部能够清除计时器
    return timer
  }
}

这个函数接受两个参数:

  • fn — 需要进行防抖的函数。
  • wait — 在调用 fn 函数之前需要等待的时间(以毫秒为单位)。

然后它返回一个包装函数,该函数会将原定时器清除并重新计时。在规定时间内,如果再次调用包装函数,则会将原定时器清除并重新计时。

另外,你可以进一步改进该防抖函数,例如添加一个可选参数,使包装函数能够立即调用 fn 函数。这里我们不在介绍,详细内容可以在最后提供的资料中找到答案。

示例:检测是否触底

查看是否触底,常用于触底加载更多数据:

const isAtBottom = function () {
  console.log(
    document.documentElement.clientHeight + window.scrollY >=
      document.documentElement.scrollHeight
  )
}

document.addEventListener('scroll', debounce(isAtBottom, 1000))

查看效果

节流

节流(throttle)是指在一段时间内,只允许函数被调用一次。

与防抖不同,节流函数在等待期间不会重置计时器。如果在等待期间多次调用函数,只有第一次会被执行,其他调用会被忽略。

有两种实现方式:时间戳和定时器

时间戳

function throttle(fn, wait) {
  let previous = 0

  return function () {
    const now = Date.now()
    if (now - previous > wait) {
      fn.apply(this, arguments)
      previous = now
    }
    return fn
  }
}

它返回一个包装函数,该函数会检查与上一次调用之间是否已经过了规定的时间。如果是,则调用 fn 函数并更新上一次调用的时间。否则,不会调用 fn 函数。

定时器

function throttle(fn, wait) {
  let timer = null

  return function () {
    if (timer) return
    timer = setTimeout(() => {
      fn.apply(this, arguments)
      timer = null
    }, wait)
    return timer
  }
}

它返回一个包装函数,该函数会在第一次调用时设置一个定时器。在等待期间,如果再次调用该函数,则不会执行任何操作。在定时器到期后,会调用 fn 函数并清除定时器。

区别

两者的区别在于,函数节流是在一段时间内最多调用一次,而函数防抖是在一段时间内只调用一次。

一段时间内最多调用一次意味着,如果你在这段时间内多次调用函数,那么只有第一次调用会生效,之后的调用都会被忽略。

一段时间内只调用一次意味着,如果你在这段时间内多次调用函数,那么只有最后一次调用会在这段时间结束后生效,之前的调用都会被忽略。

使用场景

函数节流适用于需要限制调用频率的场景,而函数防抖适用于需要等待用户输入完成后才进行响应的场景。

最后

本文我们实现了基本够用的节流和防抖,你还可以添加 lodash 这类工具库提供对节流和防抖的各种功能处理,以适用各种项目。

更多详细内容可以阅读以下文章: