资讯专栏INFORMATION COLUMN

JS throttle与debounce的区别

wawor4827 / 3300人阅读

摘要:可以看下面的栗子这个图中图中每个小格大约,右边有原生事件与节流去抖插件的与事件。即如果有连续不断的触发,每执行一次,用在每隔一定间隔执行回调的场景。执行啦打印执行啦打印执行啦节流按照上面的说明,节流就是连续多次内的操作按照指定的间隔来执行。

一般在项目中我们会对input、scroll、resize等事件进行节流控制,防止事件过多触发,减少资源消耗;在vue的官网的例子中就有关于lodash的debounce方法的使用,当时也提到了throttle,但一直没搞明白节流 throttle去抖 debounce具体区别在哪里,所以花了点时间来搞清楚。

1. 区别

节流 throttle去抖 debounce的区别主要在触发时机上:

debounce(func, wait, options):创建并返回函数的防反跳版本,将延迟函数的执行(真正的执行)在函数最后一次调用时刻的wait毫秒之后,对于必须在一些输入(多是一些用户操作)停止之后再执行的行为有帮助。将一个连续的调用归为一个,如果连续在wait毫秒内调用,最后只有最后一次会执行

throttle(func, wait, options):创建并返回一个像节流阀一样的函数,当重复调用函数的时候,最多每隔指定的wait毫秒调用一次该函数;不允许方法在每wait毫秒间执行超过一次,如果连续在wait毫秒内调用,最后执行会均匀分布在大约每wait一次

对于lodash来说,throttle是调用debounce来实现的,throttle 和 debounce 最终都会都会调用 debounce 方法。当调用 _.debouncelodash会返回一个函数,这个函数在被调用时会生成一个 setTimeout(delayed, delay)。其中 delayed 又是一个内部方法,在 delayed 被调用时进行如下检测:当前时间 - 上次func被调用事件 是否 小于 0 或 大于 delay ?如果是则执行一次 func,记录并返回执行结果,同时更新上次被调用时间;如果不是则调用 setTimeout 进行下一次的判断。_.throttle 方法只不过是多给 debounce 传了一个 options = {maxWait: $maxWait, leading: true, trailing: true},这个选项的意思是至少保证在每 maxWait 时间让 func 被调用一次。

可以看下面的栗子:

这个图中图中每个小格大约30ms,右边有原生mouseover事件、lodash与jQuery节流去抖插件的debounce与throttle事件。
在图左区域移动鼠标时:对于debounce,mouseover事件一直没有被调用,直到停下来才被调用一次。而throttle是每wait毫秒就调用一次。

2. 使用场景

debounce:第一次触发后,进行倒计wait毫秒,如果倒计时过程中有其他触发,则重置倒计时;否则执行。用它来丢弃一些重复的密集操作,直到流量减慢。
throttle:第一次触发后先执行fn(lodash可以通过{leading: false}来取消),然后wait ms后再次执行,在单位wait毫秒内的所有重复触发都被抛弃。即如果有连续不断的触发,每wait ms执行fn一次,用在每隔一定间隔执行回调的场景。

mouse move 时减少计算次数:debounce

input 中输入文字自动发送 ajax 请求进行自动补全: debounce

ajax 请求合并,不希望短时间内大量的请求被重复发送:debounce

resize window 重新计算样式或布局:debouncethrottle

scroll 时触发操作,如随动效果:throttle

对用户输入的验证,不想停止输入再进行验证,而是每n秒进行验证:throttle

3. 简单实现 3.1 去抖 debounce

按照上面的说明,去抖就是连续多次delay内的操作取最后一次操作真正执行。

let reduceEvent
function debounce(cb, delay) {
  if (!reduceEvent) {
    reduceEvent = setTimeout(() => {
      cb()
      console.log("执行啦!!")
      reduceEvent = null
    }, delay)
  }
}

setTimeout(() => debounce(() => console.log(1), 2000), 1000)         // 打印: 1 执行啦!!
setTimeout(() => debounce(() => console.log(2), 2000), 2000)
setTimeout(() => debounce(() => console.log(3), 2000), 2000)
setTimeout(() => debounce(() => console.log(4), 2000), 4000)         // 打印: 4 执行啦!!
3.2 节流 throttle

按照上面的说明,节流就是连续多次delay内的操作按照指定的间隔来执行。

function throttle(func, wait = 200) {
  let last = 1
  let timer
  return function(...rest) {
    const now = +new Date()
    if (last && now - last < wait) {
      clearTimeout(timer)
      timer = setTimeout(() => {
        last = now
        func.apply(this, rest)
      }, wait)
    } else {
      last = now
      func.apply(this, rest)
      clearTimeout(timer)
    }
  }
}
const task = throttle(() => console.log(1), 2000)
setTimeout(task, 0)
setTimeout(task, 500)
setTimeout(task, 1000)
setTimeout(task, 2000)                 // 打印: 1 1

网上的帖子大多深浅不一,甚至有些前后矛盾,在下的文章都是学习过程中的总结,如果发现错误,欢迎留言指出~

参考:

lodash

图解 debounce 与 throttle 的区别

debounce与throttle区别

Debouncing and Throttling Explained Through Examples

Debounce and Throttle: a visual explanation

PS:欢迎大家关注我的公众号【前端下午茶】,一起加油吧~

另外可以加入「前端下午茶交流群」微信群,长按识别下面二维码即可加我好友,备注加群,我拉你入群~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94122.html

相关文章

  • throttledebounce区别

    摘要:自己尝试一下年在的文章中第一次看到的实现方法。这三种实现方法内部不同,但是接口几乎一致。如你所见,我们使用了参数,因为我们只对用户停止改变浏览器大小时最后一次事件感兴趣。 前几天看到一篇文章,我的公众号里也分享了《一次发现underscore源码bug的经历以及对学术界拿来主义的思考》具体文章详见,微信公众号:showImg(https://segmentfault.com/img/b...

    Pluser 评论0 收藏0
  • Debounce vs Throttle

    摘要:那么还有最后一个问题,那我之前设置的定时器怎么办呢定时器执行的是这个函数,而这个函数又会通过进行一次判断。 我们在处理事件的时候,有些事件由于触发太频繁,而每次事件都处理的话,会消耗太多资源,导致浏览器崩溃。最常见的是我们在移动端实现无限加载的时候,移动端本来滚动就不是很灵敏,如果每次滚动都处理的话,界面就直接卡死了。 因此,我们通常会选择,不立即处理事件,而是在触发一定次数或一定时间...

    xcold 评论0 收藏0
  • 【译】通过例子解释 DebounceThrottle

    摘要:举例举例通过拖拽浏览器窗口,可以触发很多次事件。不支持,所以不能在服务端用于文件系统事件。总结将一系列迅速触发的事件例如敲击键盘合并成一个单独的事件。确保一个持续的操作流以每毫秒执行一次的速度执行。 Debounce 和 Throttle 是两个很相似但是又不同的技术,都可以控制一个函数在一段时间内执行的次数。 当我们在操作 DOM 事件的时候,为函数添加 debounce 或者 th...

    LeoHsiun 评论0 收藏0
  • JS - debounce(去抖) 和 throttle(节流)

    摘要:多次连续事件触发动作最后一次触发之后的指定时间间隔执行回调函数预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新的时间周期。 定义 为了避免某个事件在较短的时间段内(称为 T)内连续触发从而引起的其对应的事件处理函数不必要的连续执行的一种事件处理机制(高频触发事件解决方案)debounce:当调用动作触发一段时间后,才会执行该动作,若在这段时间间隔内又...

    Mike617 评论0 收藏0
  • 关于js节流函数throttle和防抖动debounce

    摘要:主要实现在于通过异步操作的事件间隔,对于前后两次调用方法打时间进行比较,用清空定时器的操作实现多余调用操作的舍弃。 废话不多说,直奔主题。 什么是throttle和debounce? 这两个方法的主要目的多是用于性能优化。最常见的应用尝尽就是在通过监听resize、scroll、mouseover等事件时候的性能消耗。拿scroll来说,没有处理时滑动一次滚动条scroll事件会触发多...

    张红新 评论0 收藏0

发表评论

0条评论

wawor4827

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<