6

细说节流(Throttle)和防抖(Debounce)

 3 years ago
source link: https://www.techug.com/post/elaborate-on-throttle-and-debounce.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

细说节流(Throttle)和防抖(Debounce)

2

节流(Throttle)和防抖(Debounce)对于前端开发人员来说应该是十分熟悉的,节流(Throttle)和防抖(Debounce)是两种可以节省性能的编程技术,两者的目的都是为了优化性能,提高用户体验,都是基于 DOM 事件限制正在执行的 JavaScript 数量的方法。但两者的有什么不一样呢?

节流会强制执行一个函数在一段时间内可以被调用的最大次数。如“最多每 100 毫秒执行一次此函数”。

假设在正常情况下,会在 10 秒内调用此函数 1,000 次。如果将其限制为每 100 毫秒仅一次,则该函数最多只会执行 100 次。

  • (10s * 1,000) = 10,000 ms

  • 10,000 ms / 100 ms 限制 = 100 个最大调用

防抖强制一个函数在一段时间内没有被调用之前不会被再次调用。如“仅当 100 毫秒过去了而没有被调用时才执行此函数”。

也许一个函数在短时间内被调用 1000 次,分散在 3 秒内,然后停止调用。如果在 100 毫秒的时间内启动,这个功能只会在 3.1 秒的时间内启动一次。每次在突发事件期间调用该函数时,它都会重置恢复计时器。

区别是什么?

这些概念的一个主要用例是某些 DOM 事件,例如滚动和调整大小。例如,如果将滚动处理程序附加到一个元素,并将该元素向下滚动 5000 像素,可能会看到 100 多个事件被触发。如果事件处理程序做了大量工作(例如繁重的计算和其他 DOM 操作),可能会看到性能问题(卡顿)。如果可以减少执行该处理程序的次数,而不会对经验造成太大影响,那么这可能是值得的。

常用的场景如下:

  • 等到用户停止调整窗口大小

  • 在用户停止输入之前不要触发 AJAX 事件

  • 监测或者获取页面的滚动位置,最多每 100ms 响应一次

  • 在应用中拖动元素时确保良好的性能

节流(Throttle)和防抖(Debounce)两个函数都内置到 Lodash 脚本库中,无需自己实现。

节流(Throttle)场景

$("body").on("scroll", _.throttle(function() {
    // 处理逻辑
}, 100));

防抖(Debounce)场景

实际生活中,如百度搜索,输入文本后会出现下拉选择,这个过程一般绑定文本事件 keypress

下图描述了使用防抖(Debounce)前状态的性能监控捕获,每次 keypress 引发事件时,它都会触发搜索引擎请求数据并将结果呈现在屏幕上。事实上,这些结果并没有被用户看到,因为它们已经被最新 keypress 事件的后续结果覆盖了,屏幕上仅呈现最新结果。

正如所看到的,搜索过程和结果呈现只调用一次(当用户完成输入时),没有重复调用不重要的功能,如布局渲染、内存处理、DOM 元素管理。

下面是以搜索为场景,展示 AJAX 的请求情况:

还有下面的窗口大小调整场景,如下:

$(window).on("resize", _.debounce(function() {
   // 处理逻辑
}, 100));

在现代浏览器中,可以使用 requestAnimationFrame,告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

节流(Throttle)和防抖(Debounce)这两个来自于需要延迟功能的执行,因为用户不想进行过多的 HTTP 请求。如今,这些是提高 Web 性能的重要方法。

本文文字及图片出自 InfoQ


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK