Debounce 和 Throttle 的原理及实现

Debounce 和 Throttle 的原理及实现浏览器

  • throttle和debounce均是经过减小实际逻辑处理过程的执行来提升事件处理函数运行性能的手段,throttle并无实质上减小事件的触发次数。二者在概念理解上确实比较容易使人混淆,
  • debounce 强制函数在某段时间内只执行一次,throttle 强制函数以固定的速率执行。在处理一些高频率触发的 DOM 事件的时候,它们都能极大提升用户体验。

在处理诸如 resize、scroll、mousemove 和 keydown/keyup/keypress 等事件的时候,一般咱们不但愿这些事件太过频繁地触发,尤为是监听程序中涉及到大量的计算或者有很是耗费资源的操做。闭包

有多频繁呢?以 mousemove 为例,根据 DOM Level 3 的规定,「若是鼠标连续移动,那么浏览器就应该触发多个连续的 mousemove 事件」,这意味着浏览器会在其内部计时器容许的状况下,根据用户移动鼠标的速度来触发 mousemove 事件。(固然了,若是移动鼠标的速度足够快,好比“刷”一下扫过去,浏览器是不会触发这个事件的)。resize、scroll 和 key* 等事件与此相似。app

1.debounce 函数所作的事情就是,强制一个函数在某个连续时间段内只执行一次,哪怕它原本会被调用屡次。咱们但愿在用户中止某个操做一段时间以后才执行相应的监听函数,而不是在用户操做的过程中,浏览器触发多少次事件,就执行多少次监听函数。

function debounce(fn, delay) {

  // 定时器,用来 setTimeout
  var timer

  // 返回一个函数,这个函数会在一个时间区间结束后的 delay 毫秒时执行 fn 函数
  return function () {

    // 保存函数调用时的上下文和参数,传递给 fn
    var context = this
    var args = arguments

    // 每次这个返回的函数被调用,就清除定时器,以保证不执行 fn
    clearTimeout(timer)

    // 当返回的函数被最后一次调用后(也就是用户中止了某个连续的操做),
    // 再过 delay 毫秒就执行 fn
    timer = setTimeout(function () {
      fn.apply(context, args)
    }, delay)
  }
}

debounce 返回了一个闭包,这个闭包依然会被连续频繁地调用,可是在闭包内部,却限制了原始函数 fn 的执行,强制 fn 只在连续操做中止后只执行一次。函数

Throttle

throttle 的概念理解起来更容易,就是固定函数执行的速率,即所谓的“节流”。正常性能

/**
*
* @param fn {Function}   实际要执行的函数
* @param delay {Number}  执行间隔,单位是毫秒(ms)
*
* @return {Function}     返回一个“节流”函数
*/

function throttle(fn, threshhold) {

  // 记录上次执行的时间
  var last

  // 定时器
  var timer

  // 默认间隔为 250ms
  threshhold || (threshhold = 250)

  // 返回的函数,每过 threshhold 毫秒就执行一次 fn 函数
  return function () {

    // 保存函数调用时的上下文和参数,传递给 fn
    var context = this
    var args = arguments

    var now = +new Date()

    // 若是距离上次执行 fn 函数的时间小于 threshhold,那么就放弃
    // 执行 fn,并从新计时
    if (last && now < last + threshhold) {
      clearTimeout(timer)

      // 保证在当前时间区间结束后,再执行一次 fn
      timer = setTimeout(function () {
        last = now
        fn.apply(context, args)
      }, threshhold)

    // 在时间区间的最开始和到达指定间隔的时候执行一次 fn
    } else {
      last = now
      fn.apply(context, args)
    }
  }
}

二者应用以后,直接带来的效率。若是仍是不能彻底体会 debounce 和 throttle 的差别,能够到 这个页面 看一下二者可视化的比较。
clipboard.png
参考地址this

相关文章
相关标签/搜索