[译]通过实例讲解Debouncing和Throtting(防抖与节流)
栏目: JavaScript · 发布时间: 5年前
内容简介:lodash源码中推荐的文章,为了学习(英语),翻译了一下~作者:DAVID CORBACHO
lodash源码中推荐的文章,为了学习(英语),翻译了一下~
作者:DAVID CORBACHO
本文来自一位伦敦前端工程师 DAVID CORBACHO
的技术投稿。我们在之前讨论过这个话题(关于防抖与节流),但这次, DAVID CORBACHO
通过生动的演示会将它们讲的十分清晰,通俗易懂。
Debounce
和 throttle
是两个相似(但实现原理不一样)的技术手段,用于控制一个函数在一段时间内执行几次。
当我们的函数附着在 dom
事件上时,使用 Debounce
和 throttle
去处理这个函数是十分有用的。为什么呢?因为我们在事件和执行函数之间加了一个控制层。需要注意的是,这里并不是去控制 dom
事件发生的频率。
我们来看一个滑动事件的例子:
当我们使用触控板、滚轮、或者是拉动滑动条,事件可能每秒仅仅触发了30次左右。但如果我们滑的比较慢,他可能触发100次。对于这些不一致的数据,你在处理的时候是否考虑到了?
2011年的时候,推特网上出现了一个问题:当你缓慢地在推特上往下滚动时,网站开始变得卡顿甚至没有反应。 John Resig
针对该问题发了一条博客 learning-from-twitter ,他觉得在 scroll
事件上附着复杂的函数处理是十分糟糕的。
John给出的解决方案是在scroll事件结束后,每250毫秒做循环执行(感兴趣的可以去看上面那篇博客,此时应该是Debounce得雏形)。这种处理耦合度低,而且避免了破坏用户体验。
如今处理事件的方式复杂了不少,下面向你们介绍 Debounce
, Throttle
,对应的也举一些例子。
Debounce
Debounce
将一个组的多次调用处理为只调用一次。
想象你正在电梯里,电梯门准备关闭,这时候有个人同时进电梯,此时电梯并没有开始上升(下降),而是电梯门再次打开。如果不断地有人进来,电梯将延迟他上升(或下降)的函数,从而达到资源优化的目标。
你可以自己试试,点击或者将鼠标放在按钮上。
可以看到 debounce
将多次连续的事件整理成单次的事件。
Leading edge (or "immediate") [首次或立即]
你可能发现防抖事件在等待触发事件执行,直到事件都结束后它才执行。为什么不让事件一开始就执行,从而达到跟我们最初的设想一样的效果呢?但是短时间内不能连续执行。
你可以看看这个,这是个"leading" debounce
的例子。
在 underscore.js
中,该配置项叫 immediate
而不是 leading
。
你可以试试:
Debounce 的实现
我第一次看到 debounce
的实现是在 John Hann(term之父)
的博客中,当时还是2009年。一年过后 Jeremy Ashkenas
将它加入了 underscore.js 。 debounce
最近才加入到 Lodash
中。
这三种实现方式内部有些不同,但他们的接口十分相似。
曾经有一段时间underscore采用了debounce中debounce/throttle 的实现,知道2013年我在 _.debounce
中发现了一个bug,从那之后,他们分道扬镳。
Lodash
加了很多特征在 _.debounce
和 _.throttle
中。原来的 immediate
标识被替换成 leading
和 trailing
。你可以配置一项,或者都配置。默认生效的是 trailing
。
我在本文中不会讨论新的配置项 maxWait
,虽然我不讨论他,但是他很有用。事实上 throttle
的实现就是在 debounce
中使用了 maxWait
,你可以在 这里 看到。
Debounce 举例
Resize 的例子
当我们在调整浏览器窗口时,会触发 Resize
事件。
看下面的 demo
:
可以看到,我们在 resize
事件中使用默认配置 trailing
,因为我们在调整窗口大小后只去最后一次的值。
键盘输入自动发送ajax请求
我们做的处理是当用户在输入时,每50毫秒向后台发送一次 ajax
请求。这时使用 _.debounce
能帮我们避免许多额外的消耗,我们仅仅在用户停止输入后发送一次请求。
这里使用 leading
是没有意义的,我们需要等待用户最后一个字符敲下。
类似此场景的一个例子是进行输入验证,比如用户在注册时提示“密码不足6位”。
如何使用debounce和throttle以及常见的坑
许多人往往更倾向于写自己的 debounce/throttle
函数,或者 ctrlC ctrlV
别人博客里的代码。我的建议是正确的去使用 underscore
和 Lodash
。如果你仅仅需要 _.debounce
和 _.throttle
方法,你可以使用 lodash-cli
生成指定函数的js,使用方法如下:( webpack
等打包 工具 的出现我觉得不必考虑此问题)
npm i -g lodash-cli lodash include = debounce, throttle 复制代码
简单使用:
// WRONG $(window).on('scroll', function() { _.debounce(doSomething, 300); }); // RIGHT $(window).on('scroll', _.debounce(doSomething, 200)); // or var debounced_version = _.debounce(doSomething, 200); $(window).on('scroll', debounced_version); // If you need it debounced_version.cancel(); 复制代码
Throttle
Throttle
的作用是确保我们的函数在每一个毫秒区间只执行一次。
Throttle
和 debounce
主要的不同在于,监听的事件一直在发生, Throttle
能确保我们执行的函数在一个毫秒区间内至少执行一次。这里可能一时难以理解,但看了下面的例子之后,也许你就会茅塞顿开。
Throttling Examples
无限下拉
一个常见的场景,用户在下拉页面,你需要去监测用户离底部多远,如果接近底部时,发送一个 ajax
请求获取更多内容,然后再拼接到页面上。
讨巧的 debounce在
这个场景下一点办法都没有,它只会在用户停止滑动动作后触发。我们需要的是用户在接近底部时发送请求,此时用户可能正在下拉滑动条。
有了 throttle
我们可以经常计算用户离底部的距离。
如有帮助,感谢点赞!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
编程珠玑(第2版•修订版)
[美] Jon Bentley 乔恩•本特利 / 黄倩、钱丽艳 / 人民邮电出版社 / 2014-12 / 39
历史上最伟大的计算机科学著作之一 融深邃思想、实战技术与趣味轶事于一炉的奇书 带你真正领略计算机科学之美 多年以来,当程序员们推选出最心爱的计算机图书时,《编程珠玑》总是位于前列。正如自然界里珍珠出自细沙对牡蛎的磨砺,计算机科学大师Jon Bentley以其独有的洞察力和创造力,从磨砺程序员的实际问题中凝结出一篇篇不朽的编程“珠玑”,成为世界计算机界名刊《ACM通讯》历史上最受欢......一起来看看 《编程珠玑(第2版•修订版)》 这本书的介绍吧!