throttle
概念:触发函数事件后,短时间间隔内无法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用 适用场景:窗口调整(resize)、页面滚动(scroll)、抢购疯狂点击(movedown)
function throttle(fn, interval) {
let last = 0;
return function() {
let context = this;
let args = arguments;
let now = new Date.getTime();
if(now - last >= interval) {
fn.apply(context, args);
last = now;
}
}
}
debounce
在特定时间延迟内连续多次触发事件后,事件处理函数只执行一次,并且是在触发操作结束时执行 适用场景: 实时搜索(keyup)、拖拽(mousemove)
function debounce(fn, delay) {
let timer = null;
return function () {
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(this, args);
}, delay);
}
}
## 用 Throttle 来优化 Debounce
如果用户的操作十分频繁——每次都不等 debounce 设置的 delay 时间结束就进行下一次操作,于是每次 debounce 都为该用户重新生成定时器,回调函数被延迟了不计其数次。频繁的延迟会导致用户迟迟得不到响应,用户同样会产生“这个页面卡死了”的观感。
为了避免这个问题,我们需要改进:delay的时间到了,必须要给用户一个响应,也就是要调用一次执行函数。
function throttle(fn, delay) {
let timer = null, last = 0;
return function() {
let context = this;
let args = arguments;
let now = new Date.getTime();
// 确保delay的时间内至少执行一次
if (now - last >= delay) {
fn.apply(this, args);
last = now;
} else {
clearTimeout(timer);
timer = setTimeout(function() {
last = now;
fn.apply(this, args);
}, delay);
}
}
}