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

节流和防抖在咱们平时的项目中挺经常使用的,也是面试中常常会被提问的知识点,今天咱们一块儿来学习一下。html

节流

简单理解就是:控制函数每隔n秒执行一次。前端

做用

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

应用场景

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

示例

这边咱们以onscroll来写个例子,加深理解。浏览器

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

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

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

咱们来看下浏览器的打印结果,看如下gif图:函数

能够看到,函数执行了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次。测试

经过一个定时器,咱们控制函数每隔500毫秒再执行一次,大大下降了执行频率,从而提高性能。动画

节流概念理解

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

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

防抖

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

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

防抖概念理解

能够想象一下作电梯,当有人进入电梯(触发事件),那电梯将在10秒后出发(执行事件),这时若是又有人进入电梯了(在10秒内再次触发了事件),咱们又得从新等10秒才能触发(从新计时)。

示例

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

看代码:

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

obj.onkeyup = function () {
  _count++;
  console.log('执行次数:' + _count);
}
复制代码

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

咱们只能假设用户在停顿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);
}
复制代码

经过动图,能够看到,当我一直输入的时候,事件是不会被触发的,直到我中止输入才会触发一次。

实现思路:咱们把目标代码放入到一个定时器里,若是事件被频繁的触发,目标代码将不会被执行。为何不执行呢,由于咱们前面加了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…

关注

欢迎你们关注个人公众号前端帮帮忙,一块儿交流学习,谢谢~

参考: zhuanlan.zhihu.com/p/38313717

相关文章
相关标签/搜索