写点什么

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

用户头像
devpoint
关注
发布于: 2021 年 07 月 24 日
细说节流(Throttle)和防抖(Debounce)

节流(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 事件的后续结果覆盖了,屏幕上仅呈现最新结果。



下面是使用防抖(Debounce)进行优化后的结果,如下:



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


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



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


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


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

总结

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

用户头像

devpoint

关注

细节的追求者 2011.11.12 加入

专注前端开发,用技术创造价值!

评论

发布
暂无评论
细说节流(Throttle)和防抖(Debounce)