【前端帮帮忙】第7期 关于节流(throttle)和防抖(debounce)的理解

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

内容简介:防止用户高频率的触发事件,刚好这个事件又需要处理大量的计算和渲染而带来的性能问题。这边我们以比如有这样一个场景:我们需要判断浏览器滚动条滚动到底部的时候去动态加载一些数据,可能我们直接就会写上以下的代码:

防止用户高频率的触发事件,刚好这个事件又需要处理大量的计算和渲染而带来的性能问题。

应用场景

  • onscroll
  • onresize
  • mousemove
  • touchmove
  • ...

示例

这边我们以 onscroll 来写个例子,加深理解。

比如有这样一个场景:我们需要判断浏览器滚动条滚动到底部的时候去动态加载一些数据,可能我们直接就会写上以下的代码:

let obj = document.querySelector('.throttle-test');
let _count = 0;

obj.onscroll = function () {
  // 假设已经滚动到底部了,我们给_count加1。
  _count++;
  console.log('执行次数:' + _count);
}
复制代码

我们来看下浏览器的打印结果,看以下gif图:

【前端帮帮忙】第7期 关于节流(throttle)和防抖(debounce)的理解

可以看到,函数执行了20次,很显然这并不是我们想要的,因为 onscroll 事件并不会等你滚动到底部了再去触发事件,而是会不间断的触发,这就很容易引发一些性能问题,这时候就需要用到节流了。

我们把代码做下修改:

let obj = document.querySelector('.throttle-test');
let _count = 0;
let _canRun = true;
obj.onscroll = function () {
  if (!_canRun) {
    return false;
  }
  _canRun = false;
  setTimeout(function () {
    // 假设已经滚动到底部了,我们给_count加1。
    _count++;
    console.log('执行次数:'+_count);
    _canRun = true;
  }, 500);
}
复制代码

通过以下gif图,我们可以看到,函数最终只执行了2次。

【前端帮帮忙】第7期 关于节流(throttle)和防抖(debounce)的理解

通过一个定时器,我们控制函数每隔500毫秒再执行一次,大大降低了执行频率,从而提升性能。

节流概念理解

节流跟防抖,它们既有相似之处但又有所不同,很容易混淆。这里通过比喻来加深理解,先来说说节流。

节流的概念可以想象一下水坝,你建了水坝在河道中,不能让水流动不了,你只能让水流慢些。换言之,你不能让用户的方法都不执行。(个人比较喜欢这个比喻,因为它很形象的说出了跟防抖的区别。)

防抖

控制函数在n秒内只能执行一次,如果用户在n秒内重复的触发事件,则重新计时且函数不会被执行,只有等到用户不再触发事件的时候才去执行一次。

作用跟 节流 类似,也是为了防止用户高频率的触发事件所引发的性能问题。

防抖概念理解

可以想象一下做电梯,当有人进入电梯(触发事件),那电梯将在10秒后出发(执行事件),这时如果又有人进入电梯了(在10秒内再次触发了事件),我们又得重新等10秒才能触发(重新计时)。

示例

有个文本框让用户填写用户名,当用户输入字符时,我们需要实时发请求到后台去验证用户名是否有重复的。实际上,在加入防抖机制前,用户输入 helloworld 后,我们已经发送了10次请求了,很显然是不可取的。

看代码:

let obj = document.querySelector('#testInput');  // 获取文本输入框
let _count = 0;

obj.onkeyup = function () {
  _count++;
  console.log('执行次数:' + _count);
}
复制代码
【前端帮帮忙】第7期 关于节流(throttle)和防抖(debounce)的理解

我们来给代码加入防抖机制:

我们只能假设用户在停顿n秒内没有再触发事件,我们就判定用户已经输入完成了,这时再发送请求。

看代码:

let obj = document.querySelector('#testInput');
let timer = null;
let _count = 0;

obj.onkeyup = function () {
  clearTimeout(timer);  // 清除定时器,重新计时
  timer = setTimeout(function () {
    _count++;
    console.log('执行次数:'+_count);
  }, 800);
}
复制代码
【前端帮帮忙】第7期 关于节流(throttle)和防抖(debounce)的理解

通过动图,可以看到,当我一直输入的时候,事件是不会被触发的,直到我停止输入才会触发一次。

实现思路:我们把目标代码放入到一个定时器里,如果事件被频繁的触发,目标代码将不会被执行。为什么不执行呢,因为我们前面加了 clearTimeout 。相当于中途不断的有人进入电梯,电梯又得重新倒计时10秒才会启动一样,直到用户没再输入了(没人再进入电梯了),这时候目标代码才会按照我们设定的时间再去执行一次(电梯才会启动)。

节流和防抖的区别

  • 节流:目标代码会按照我们设定的时间间隔即每隔n秒就执行一次
  • 防抖:在用户不触发事件时,才去执行目标代码,并且抑制了本来在事件中要执行的动作;当事件被一直触发的情况下,目标代码有可能不会被执行
  • 函数节流会用在比 input , keyup 更频繁触发的事件中,如 resize , touchmove , mousemove , scroll节流 会强制函数以固定的速率执行。因此这个方法比较适合应用于动画相关的场景。

最后

感谢您的阅读,希望对你有所帮助。文中如果有描述不当的地方,烦请指正,感激不尽。 另外文中所演示的代码仅用来测试使用,并不适合用在实际开发中,实际开发可以使用 Lodash 库中的 节流防抖 方法,这里就不贴代码了,毕竟考虑的比较全面哈。

Lodash 库的地址:

节流: www.lodashjs.com/docs/4.17.5…

防抖: www.lodashjs.com/docs/4.17.5…


以上所述就是小编给大家介绍的《【前端帮帮忙】第7期 关于节流(throttle)和防抖(debounce)的理解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Spark SQL内核剖析

Spark SQL内核剖析

朱锋、张韶全、黄明 / 电子工业出版社 / 2018-8 / 69.00元

Spark SQL 是 Spark 技术体系中较有影响力的应用(Killer application),也是 SQL-on-Hadoop 解决方案 中举足轻重的产品。《Spark SQL内核剖析》由 11 章构成,从源码层面深入介绍 Spark SQL 内部实现机制,以及在实际业务场 景中的开发实践,其中包括 SQL 编译实现、逻辑计划的生成与优化、物理计划的生成与优化、Aggregation 算......一起来看看 《Spark SQL内核剖析》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具