>防抖与节流是前端性能优化中很重要的一环,防抖可以用来减少页面请求数量,节流则可以用于减少监听事件回调函数的触发次数。
防抖与节流都是用来减少页面开销的方法,在我们常用的loadsh库中就提供了这些方法,本章主要讲述防抖与节流的理念,让我们在知其然的情况下更知其所以然。
<br />
### 防抖概念
一般用于用户在一定时间内不触发特定动作时再触发回调函数。主要适用于搜索框的情况,拼音输入法存在一个问题在于每键入一个字母就会去搜索一次,但是这时候往往用户是没有完成输入的,在这种情况下可以通过防抖的方法来解决这个问题,在一定时间内用户没有重新触发特定的动作再去触发这个动作对应的回调函数。
举个🌰:
在淘宝上和卖家产生纠纷时,找淘宝人工客服,一般问题解决后会结束会话,但是在忘记结束会话的情况下,在一定时间内我们没有给客服回复时会自动结束会话,但如果我们在这个时间段内随便说一个字,这个时间就会重新计时,这和防抖机制是相似的。
代码来说话
```javascript
function debounce (fn, timeout) {
// 添加定时器变量
let timer = null;
return function () {
// 保留this
let that = this;
// 记录参数
let args = arguments;
// 获取当前时间,并将其转化为时间戳
let now = +new Date();
// 如果存在定时器,清除上一个定时器
if (timer) {
clearTimeout(timer);
}
// 设定新的定时器
setTimeout(() => {
fn.apply(that, args);
last = now;
}, timeout)
}
}
const clickTarget = document.getElementById('btn');
clickTarget.addEventListener('click', debounce(() => {
console.log('2s内无操作,触发防抖事件');
}, 2000))
```
<br />
### 节流概念
节流一般用与懒加载的情况下,懒加载需要实时监控页面滚动距离以及元素是否显示在所见的文档流当中,但有时候用户会频繁的上下滚动但不会触发修改src事件,这会导致页面性能很低,因此会做节流处理。
举个🌰:
在游乐场玩的时候,我们需要排队,就算没有人来的项目也是按时开启的,只要到了项目开始的时间,就立马开始不会等待。后续的任务都要留在下一次执行。
代码说话
```javascript
function throttle(fn, delay) {
let time = 0;
return function () {
let now = +new Date();
let that = this;
if (now - time >= delay) {
time = now;
fn.apply(that, arguments);
}
}
}
const clickTarget = document.getElementById('btn');
clickTarget.addEventListener('click', throttle(() => {
console.log('时间到达2s,触发节流事件');
}, 2000))
```
<br />
### 实际使用
在实际使用中,我们会将防抖和节流结合起来使用,如果单纯的使用防抖的话只要中间有变动任务就会无限制的延期,这并不是我们想要的。
还是拿游乐场来举个🌰:
游乐场现在有个项目,在排队过程中,只要有人来就要记录当前来人的时间,如果在之后的两分钟内没有新的游客来排队,就直接开始游戏,但如果只是这个规格会存在一个问题,如果后续一直来人游戏就无法开始,因此有了另一个规则,只要距离上一次游戏结束20分钟后就必须开启新的游戏,而不管后续有没有人来,这样会保证排队的游客不会等待太长的时间。
代码说话
```javascript
function dethrottle (fn, timeout, interval) {
let timer = null;
let last = 0;
return function() {
let that = this;
let args = arguments;
let now = +new Date();
// 超过最长时间限制后就强制执行,并清除定时器
if (now - last > interval) {
timer ? cleartTimeout(timer) : null;
last = now;
fn.apply(that, args);
} else {//不超过就重新设置定时器
timer = setTimeout(() => {
fn.apply(that, args);
}, timeout)
}
}
}
```