资讯专栏INFORMATION COLUMN

[译]通过实例讲解Debouncing和Throtting(防抖与节流)

Jenny_Tong / 1467人阅读

摘要:译通过实例讲解和防抖与节流源码中推荐的文章,为了学习英语,翻译了一下原文链接作者本文来自一位伦敦前端工程师的技术投稿。首次或立即你可能发现防抖事件在等待触发事件执行,直到事件都结束后它才执行。

[译]通过实例讲解Debouncing和Throtting(防抖与节流)

lodash源码中推荐的文章,为了学习(英语),翻译了一下~

原文链接

作者:DAVID CORBACHO

本文来自一位伦敦前端工程师DAVID CORBACHO的技术投稿。我们在之前讨论过这个话题(关于防抖与节流),但这次,DAVID CORBACHO通过生动的演示会将它们讲的十分清晰,通俗易懂。

Debouncethrottle是两个相似(但实现原理不一样)的技术手段,用于控制一个函数在一段时间内执行几次。

当我们的函数附着在dom事件上时,使用Debouncethrottle去处理这个函数是十分有用的。为什么呢?因为我们在事件和执行函数之间加了一个控制层。需要注意的是,这里并不是去控制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标识被替换成leadingtrailing。你可以配置一项,或者都配置。默认生效的是trailing

我在本文中不会讨论新的配置项maxWait,虽然我不讨论他,但是他很有用。事实上throttle的实现就是在debounce中使用了maxWait,你可以在这里看到。

Debounce 举例 Resize 的例子

当我们在调整浏览器窗口时,会触发Resize事件。

看下面的demo

demo

可以看到,我们在resize事件中使用默认配置trailing,因为我们在调整窗口大小后只去最后一次的值。

键盘输入自动发送ajax请求

我们做的处理是当用户在输入时,每50毫秒向后台发送一次ajax请求。这时使用_.debounce能帮我们避免许多额外的消耗,我们仅仅在用户停止输入后发送一次请求。

这里使用leading是没有意义的,我们需要等待用户最后一个字符敲下。

例子链接

类似此场景的一个例子是进行输入验证,比如用户在注册时提示“密码不足6位”。

如何使用debounce和throttle以及常见的坑

许多人往往更倾向于写自己的debounce/throttle函数,或者ctrlC ctrlV别人博客里的代码。我的建议是正确的去使用underscoreLodash。如果你仅仅需要_.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的作用是确保我们的函数在每一个毫秒区间只执行一次。

Throttledebounce主要的不同在于,监听的事件一直在发生,Throttle能确保我们执行的函数在一个毫秒区间内至少执行一次。这里可能一时难以理解,但看了下面的例子之后,也许你就会茅塞顿开。

Throttling Examples 无限下拉

一个常见的场景,用户在下拉页面,你需要去监测用户离底部多远,如果接近底部时,发送一个ajax请求获取更多内容,然后再拼接到页面上。

讨巧的debounce在这个场景下一点办法都没有,它只会在用户停止滑动动作后触发。我们需要的是用户在接近底部时发送请求,此时用户可能正在下拉滑动条。

有了throttle我们可以经常计算用户离底部的距离。

例子链接

如有帮助,感谢点赞!

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

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

相关文章

  • 高级函数技巧-函数抖与节流

    摘要:封装方法也比较简单,书中对此问题也进行了处理使用定时器,让函数延迟秒后执行,在此秒内,然后函数再次被调用,则删除上次的定时器,取消上次调用的队列任务,重新设置定时器。 在实际开发中,函数一定是最实用最频繁的一部分,无论是以函数为核心的函数式编程,还是更多人选择的面向对象式的编程,都会有函数的身影,所以对函数进行深入的研究是非常有必要的。 函数节流 比较直白的说,函数节流就是强制规定一...

    whinc 评论0 收藏0
  • 防抖节流的实现

    摘要:防抖防抖的作用是将多个连续的调用合并为一次调用。防抖与节流之间的重要区别是,防抖是基于上次调用来计算的而节流是基于上次调用来计算的,只要距离上次调用超过了,就可以进行下次调用。实现修改自参考资料。个人认为实现更好理解。 防抖(debounce) 防抖的作用是将多个连续的debounced调用合并为一次func调用。作用见参考资料1。 两次debounced调用的间隔小于waitTim...

    Carbs 评论0 收藏0
  • javaScript的Throttling(节流)Debouncing(防抖

    摘要:节流和防抖都是用来提高用户体验,提高网站性能的手段,它们的技术手段都是强制事件处理函数在特定的事件段内执行。针对上面举例的情况,其实运用节流和防抖都可以做到,只是它们之间又有一定的区别节流节流是在一定的时间段内,函数最多可以被调用多少次。 节流和防抖都是用来提高用户体验,提高网站性能的手段,它们的技术手段都是强制事件处理函数在特定的事件段内执行。这样解释可能还是不够直观。举两个例子吧:...

    Yujiaao 评论0 收藏0
  • VUE抖与节流的最佳解决方案——函数式组件

    摘要:案例持续触发事件时,并不立即执行函数,当毫秒内没有触发事件时,才会延时触发一次函数。也以函数形式暴露普通插槽。这样的场景组件用函数式组件是非常方便的。相关阅读函数式组件自定义指令前言 有echarts使用经验的同学可能遇到过这样的场景,在window.onresize事件回调里触发echartsBox.resize()方法来达到重绘的目的,resize事件是连续触发的这意味着echarts...

    OldPanda 评论0 收藏0
  • 小菊花课堂之JS的抖与节流

    摘要:文章来源详谈防抖和节流轻松理解函数节流和函数防抖函数防抖和节流好啦,今天的小菊花课堂之的防抖与节流的内容就告一段落啦,感各位能耐心看到这里。 前言 陆游有一首《冬夜读书示子聿》——古人学问无遗力,少壮工夫老始成。纸上得来终觉浅,绝知此事要躬行。,其中的意思想必大家都能明白,在学习或工作中,不断的印证着这首诗的内涵。所以,又有了此篇小菊花文章。 详解 在前端开发中,我们经常会碰到一些会持...

    leoperfect 评论0 收藏0

发表评论

0条评论

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