防抖和节流经常被放在一起谈论,不论是在面试过程中还是在业务都要熟悉两者的特点,才能更好的回答面试官与对业务进行优化。
防抖(debounce)
有些操作是高频触发的,但是如果每次都进行监听就会浪费许多资源,例如输入框输入的时候,我们想要在用户完成一段输入后,在进行联想操作,这时就可以使用防抖函数。
在事件被触发n秒后再执行回调,如果在这n秒内再次触发,则重新开始计时。
- 实现思路 事件触发->开启定时器->如果再次触发,则清除旧定时器,开启新定时器->时间到,执行操作
- 简单实现
function debounce(callback, delay = 1000) {
if (typeof delay !== 'number') {
throw new Error('delay must be a number');
}
if (typeof callback !== 'function') {
throw new Error('callback must be a function');
}
let _timer = null;
return function () {
clearTimeout(_timer);
_timer = setTimeout(() => {
callback.apply(this, arguments); // 绑定上下文
}, delay);
}
}
节流(throttle)
可以看出防抖函数如果在持续触发事件的时候,会存在一个问题,那就是事件将一直不触发,这显然不能满足部分场景,比如像发送一个请求,应当是点击发送按钮后,立刻发送,但是在一定时间内,不能再次触发,而这就应该使用节流函数。
在事件被触发后的n秒内,再次执行该操作,将不会再次触发事件。
- 实现思路 事件触发->执行操作->关闭阀门->阀门关闭时,事件触发将无效->时间到,打开阀门->事件触发可再次执行操作
- 简单实现
function throttle(callback, delay = 1000) {
if (typeof delay !== 'number') {
throw new Error('delay must be a number');
}
if (typeof callback !== 'function') {
throw new Error('callback must be a function');
}
let _valid = true; // 阀门
return function () {
if (_valid) {
_valid = false;
callback.apply(this, arguments);
setTimeout(() => {
_valid = true;
}, delay);
} else {
return false;
}
}
}
总结
- 防抖和节流都是为了阻止操作的高频触发,从而导致浪费性能
- 防抖是为了在一段时间内只会触发一次,节流是间隔一段时间触发一次