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

栏目: JavaScript · 发布时间: 5年前

内容简介:lodash源码中推荐的文章,为了学习(英语),翻译了一下~作者:DAVID CORBACHO

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 将一个组的多次调用处理为只调用一次。

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

想象你正在电梯里,电梯门准备关闭,这时候有个人同时进电梯,此时电梯并没有开始上升(下降),而是电梯门再次打开。如果不断地有人进来,电梯将延迟他上升(或下降)的函数,从而达到资源优化的目标。

你可以自己试试,点击或者将鼠标放在按钮上。

例子链接

可以看到 debounce 将多次连续的事件整理成单次的事件。

Leading edge (or "immediate") [首次或立即]

你可能发现防抖事件在等待触发事件执行,直到事件都结束后它才执行。为什么不让事件一开始就执行,从而达到跟我们最初的设想一样的效果呢?但是短时间内不能连续执行。

你可以看看这个,这是个"leading" debounce 的例子。

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

underscore.js 中,该配置项叫 immediate 而不是 leading

你可以试试:

例子链接

Debounce 的实现

我第一次看到 debounce 的实现是在 John Hann(term之父) 的博客中,当时还是2009年。一年过后 Jeremy Ashkenas 将它加入了 underscore.jsdebounce 最近才加入到 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 我们可以经常计算用户离底部的距离。

例子链接

如有帮助,感谢点赞!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编程珠玑(第2版•修订版)

编程珠玑(第2版•修订版)

[美] Jon Bentley 乔恩•本特利 / 黄倩、钱丽艳 / 人民邮电出版社 / 2014-12 / 39

历史上最伟大的计算机科学著作之一 融深邃思想、实战技术与趣味轶事于一炉的奇书 带你真正领略计算机科学之美 多年以来,当程序员们推选出最心爱的计算机图书时,《编程珠玑》总是位于前列。正如自然界里珍珠出自细沙对牡蛎的磨砺,计算机科学大师Jon Bentley以其独有的洞察力和创造力,从磨砺程序员的实际问题中凝结出一篇篇不朽的编程“珠玑”,成为世界计算机界名刊《ACM通讯》历史上最受欢......一起来看看 《编程珠玑(第2版•修订版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具