throttle 与 debounce
-
throttle
和debounce
是解决请求与响应速度不匹配问题的两个方案。两者的差异在于选择不同的策略。 -
debounce
的关注点是空闲的间隔时间。 -
throttle
的关注点是连续的执行间隔时间。
只要涉及到连续事件或频率控制相关的应用都可以考虑到这两个函数,比如:
- 游戏射击,keydown 事件
- 文本输入、自动完成,keyup 事件
- 鼠标移动,mousemove 事件
- DOM 元素动态定位,window 对象的 resize 和 scroll 事件
前两者debounce
和throttle
都可以按需使用;后两者肯定是用throttle
了。
throttle
_.throttle(func, wait, options)
- func 为回调函数
- wait 节流时间
- options 选项属性 1. leading 取消立即执行 2. trailing 取消最后执行
options = {
leading: false
}
或
options = {
trailing: false
}
两者只能设置其中一个
_.now = Date.now;
_.throttle = function(func, wait, options) {
let lastTime = 0;
let context;
let args;
let timeout;
const later = function() {
// 这里 leading 为 false 时,置 lastTime 值为 0 是因为下次调用 if(!lastTime ...) 这样就为 true,会执行对应语句
lastTime = options.leading === false ? 0 : _.now();
timeout = null;
func.apply(context, args);
};
return function() {
const now = _.now();
if (!lastTime && options.leading === false) {
lastTime = now;
}
const remaining = wait - (now - lastTime);
context = this;
args = arguments;
console.log(remaining);
if (remaining <= 0) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
lastTime = now;
func.apply(context, args);
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, wait);
}
};
};
debounce
_.debounce(func, wait, immediate)
- func 为防抖回调函数
- wait 为防抖时间
- immediate 设置是否立即执行
_.debounce = function(func, wait, immediate) {
let timeout;
let result;
const later = function(context, args) {
timeout = null;
if (args) result = func.apply(context, args);
};
return function(...args) {
if (timeout) clearTimeout(timeout);
if (immediate) {
const callNow = !timeout;
// 这里直接传递 later 回调函数没有传参,所以在 later 内部逻辑不会执行 func;这里的作用是为了定时
timeout = setTimeout(later, wait);
if (callNow) result = func.apply(this, args);
} else {
timeout = setTimeout(function() {
later(this, args);
}, wait);
}
return result;
};
};