节流和防抖在咱们平时的项目中挺经常使用的,也是面试中常常会被提问的知识点,今天咱们一块儿来学习一下。html
简单理解就是:控制函数每隔n秒执行一次。前端
防止用户高频率的触发事件,恰好这个事件又须要处理大量的计算和渲染而带来的性能问题。面试
这边咱们以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秒才会启动同样,直到用户没再输入了(没人再进入电梯了),这时候目标代码才会按照咱们设定的时间再去执行一次(电梯才会启动)。
input
,keyup
更频繁触发的事件中,如resize
, touchmove
, mousemove
, scroll
。节流
会强制函数以固定的速率执行。所以这个方法比较适合应用于动画相关的场景。感谢您的阅读,但愿对你有所帮助。文中若是有描述不当的地方,烦请指正,感激涕零。 另外文中所演示的代码仅用来测试使用,并不适合用在实际开发中,实际开发可使用Lodash
库中的节流
和防抖
方法,这里就不贴代码了,毕竟考虑的比较全面哈。
Lodash
库的地址:
节流:www.lodashjs.com/docs/4.17.5…
防抖:www.lodashjs.com/docs/4.17.5…
欢迎你们关注个人公众号前端帮帮忙
,一块儿交流学习,谢谢~