JS throttle与debounce的区别

JS throttle与debounce的区别

一般在项目中我们会对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

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

参考:

  1. lodash
  2. 图解 debounce 与 throttle 的区别
  3. debounce与throttle区别
  4. Debouncing and Throttling Explained Through Examples
  5. Debounce and Throttle: a visual explanation

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏高性能服务器开发

libevent源码深度剖析十一 时间管理

(1)libevent源码深度剖析一 序 (2)libevent源码深度剖析二 Reactor模式 (3)libevent源码深度剖析三 libevent基本使...

10110
来自专栏陈本布衣

treeview插件使用:根据子节点选中父节点

  鄙人公司没有专门的前端,所以项目开发中都是前后端一起抡。最近用bootstrap用的比较频繁,发现bootstrap除了框架本身的样式组件外,还提供了多种插...

60340
来自专栏Aloys的开发之路

Linux乱码问题解决方案

linux系统中文件名内容为urf8编码, windows系统中文件名默认为gbk编码, 多数文档使用gbk编码,系统采用utf8编码 无中文输入法导致的乱码 ...

56680
来自专栏崔庆才的专栏

正则表达式中零宽断言的用法

了解了正则表达式,想必一般情况下的匹配都不会出现什么问题,但是如果一些特殊情况,可能需要用到一些更高级的正则表达式匹配操作,本节我们来说明一下正则表达式的一个较...

29840
来自专栏Django中文社区

已知小问题修正

在模型中指定排序 为了让文章(Post)按发布时间逆序排列,即最新发表的文章排在文章列表的最前面,我们对返回的文章列表进行了排序,即各个视图函数中都有类似于 P...

31340
来自专栏大前端_Web

javascript运行机制:并发模型 与Event Loop

版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/articl...

26910

使用Jekyll显示Jupyter笔记本

Jekyll是一个用Ruby编写的静态站点生成器,支持博客并与Github页面整合。因为Github只负责托管,这种设置使数据分析共享和可视化变得简单。Jeky...

10520
来自专栏逸鹏说道

Python3 与 C# 并发编程之~ 线程篇2

其实以前的 Linux中是没有线程这个概念的, Windows程序员经常使用线程,这一看~方便啊,然后可能是当时程序员偷懒了,就把进程模块改了改(这就是为什么之...

20940
来自专栏用户2442861的专栏

webStorm 3.0配置使用主题背景色等

http://www.cnblogs.com/jikey/archive/2012/01/16/2323590.html

29110
来自专栏小特工作室

Navi.Soft31.开发工具(含下载地址)

1系统简介 1.1功能简述 在软件开发过程中,我们需要经常对字符串、文件、数据库操作。有时需要浏览Json格式串,有时需要浏览Xml格式串,有时需要读取txt或...

25090

扫码关注云+社区

领取腾讯云代金券