Debounce 与 Throttle:作用和区别

lodash 和其他很多工具库(比如 VueUse)都有 debounce(防抖)和 throttle(节流)的概念。简单(且有点不严谨)地讲,如果事件一直被触发,debounce 之后在最后停下来之后处理它,而 throttle 会每隔一段固定时间去处理它。

Note

在本文中我“刻意地”没有加入任何一行代码,因为发现在阅读别人的相关文章学习时,他们给出的大段代码并没有很好帮助我理解,反而是一些概念原本可以用自然语言说清楚,却非要让读者读代码来理解,造成了一个很大的 friction。如果你是那种喜欢看代码来理解的人,可以直接看 lodash 的 Debounce 源码Throttle 源码, 或者在 #参考阅读 中找篇文章看。

防抖和节流确实是非常常见和基础的东西,有能搜到的相关文章多如牛毛,我也一直在犹豫要不要吧本文发出来。最后发现本文和其他文章还是有“无代码”这个差异点,于是选择了发布。

Debounce

先从 Debounce 说起吧。一般我们把 Debounce 翻译为防抖,通常用于处理用户的文本输入。

Debounce 一个比较正式的定义来自 lodash 的文档:

Creates a debounced function that delays invoking func until after wait milliseconds have elapsed since the last time the debounced function was invoked.

这里涉及到了两个函数,第一个是原本的、需要被防抖的函数 F,第二个是 _.debounce 函数返回的、防抖过的函数 F'。这段定义就是只有在最后一次 F' 被调用若干时间后才会调用 F。如果在等待这“若干时间”里 F' 又被调用了,那么这次的调用就变成了“最后一次”,所以需要重新等待。

上面的解释还是有点抽象,用很简单的说法来说,就是如果不停的调用 F',那么真正的函数 F 不会被调用,直到对 F' 的调用停下来若干时间之后。用常见的输入框防抖来说,如果 wait 被设置成了 300 ms,那么如果用户一直以 200 ms 的间隔输入字符,那么函数一直不会被调用,直到用户停止输入(300ms)之后,F 才会被调用。

这时候看 lodash debounce 的参数, wait 的含义应该不用多说;剩下还有 maxWaitleading & trailing。这篇文章里我不打算深入研究 leadingtrailing,感兴趣的可以看 这篇文章,至于 maxWait,则是如果一直在等待的话,最多等 maxWait 毫秒就要调用一次。还是拿上面的输入框例子来说。如果设置了 maxWait 为 1000 ms,那么假如用户一直不停地输入了整整 5 秒钟,那么函数会在 1、2、3、4、5 秒后分别调用一次,因为它“最多只能等”1000ms;而如果没有 maxWait,则只会在 5s + 300ms 后调用 1 次。

Throttle

Throttle 有些人翻译成“节流阀”,但是我觉得这里应该是用动词“节流/减速” 更好,和“防抖”相对。一般来说用来处理 Resize 或者 scroll 事件。

如果你理解了 Debounce 和它的 maxWait 参数,理解 Throttle 应该是易如反掌的。先看 lodash 的定义:

Creates a throttled function that only invokes func at most once per every wait milliseconds.

也就是说,如果一直调用,那么真正的函数每 wait ms 触发一次。

有没有感觉和 debounce 的 maxWait 有点像?实际上,_.throttle 就只是 _.debounce 的一个简单包装,将 debounce 的 maxWait 设置得和 wait 一样,就得到了一个 Throttle 函数!如果感兴趣,可以看 这不到20行代码的实现

和 Debounce 一样,如果你对 leadingtrailing 参数感兴趣,可以查看 这篇文章

参考阅读

Debounce vs Throttle: Definitive Visual Guide

Throttle & Debounce behavior (lodash)

Debouncing And Throttling Explained Through Examples | CSS-Tricks

Lodash Documentation Throttle Debounce

useDebounceFn | VueUse useThrottleFn | VueUse

本文使用“署名-非商业性使用-相同方式共享 4.0 国际(CC BY-NC-SA 4.0)”进行许可。

商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接。 如果您再混合、转换或者基于本作品进行创作,您必须基于相同的协议分发您贡献的作品。

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.3.0
2023-2024 Yunfi. | Source Code RSS | Site Map Powered by Astro. See all Credits.