带你读懂防抖和节流
推荐阅读文章
1. 防抖(debounce)
描述
-
推荐阅读文章提到:
Debouncing means to coalesce several temporally close signals into one signal.
去抖动意味着将几个时间上接近的信号合并为一个信号。
实现代码
推荐阅读文章的实现:
采用两个参数:检测周期(“threshold”阈值)和一个布尔值(“execAsap”),指示信号应该发生在检测周期的开始(true)还是结束(false)。
var debounce = function (func, threshold, execAsap) {
var timeout; // 保存计时器的id, 便于取消, 同时作为锁
return function debounced () {
var obj = this, args = arguments;
function delayed () {
if (!execAsap) // execAsap 为false,信号发生在检测周期的结束(false)
func.apply(obj, args); // 执行
timeout = null; // 开锁
};
if (timeout)
clearTimeout(timeout); // 当锁关闭时,清除上一个的定时器
else if (execAsap) // execAsap 为true,信号发生在检测周期的开始(true)
func.apply(obj, args); // 执行
// 加锁,同时设置计时器id
timeout = setTimeout(delayed, threshold || 100);
};
}
使用
document.onmousemove = debounce(function (e) {
/* do something here, but only once after mouse cursor stops */
}, 250, false);
2. 节流(throttle)
描述
-
推荐阅读文章提到:
Throttling is the reduction in rate of a repeating event. Throttling is good for reducing mousemove events to a lesser, manageable rate, for instance.
节流是指降低重复事件的发生率。例如,节流有利于将鼠标移动事件减少到一个较小的、可管理的速率。
与防抖的区别:
The main difference between this and debouncing is that throttle guarantees the execution of the function regularly, at least every X milliseconds.
这与防抖之间的主要区别在于,throttle保证了函数的定期执行,至少每X毫秒执行一次。
-
mdn对Scroll事件节流的描述:
由于
scroll
事件可被高频触发,事件处理程序不应该执行高性能消耗的操作,如 DOM 操作。而更推荐的做法是使用requestAnimationFrame()
、setTimeout()
或CustomEvent
给事件节流。
实现代码
根据区别(这与防抖之间的主要区别在于,throttle保证了函数的定期执行,至少每X毫秒执行一次。)
只需修改防抖的实现代码的一部分,就可实现:
var throttle = function (func, threshold, execAsap) {
var timeout; // 保存计时器的id, 便于取消, 同时作为锁
return function debounced () {
var obj = this, args = arguments;
function delayed () {
if (!execAsap) // execAsap 为false,信号发生在检测周期的结束(false)
func.apply(obj, args); // 执行
timeout = null; // 区别:只有时间到后才开锁
};
// 区别:只有时间到后才开锁,才能进入if语句
if (!timeout) {
if (execAsap) // execAsap 为true,信号发生在检测周期的开始(true)
func.apply(obj, args); // 执行
// 加锁,同时设置计时器id
timeout = setTimeout(delayed, threshold || 100);
}
};
}
3. requestAnimationFrame
Window:requestAnimationFrame() 方法 - Web API 接口参考 | MDN (mozilla.org)
window.requestAnimationFrame()
告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
总结
-
debounce: Grouping a sudden burst of events (like keystrokes) into a single one.
debounce:将一些突发事件(如击键)分组为一个事件。
-
throttle: Guaranteeing a constant flow of executions every X milliseconds. Like checking every 200ms your scroll position to trigger a CSS animation.
throttle:保证每X毫秒执行一次的恒定流量。就像每隔200毫秒检查一次滚动位置以触发CSS动画一样。
-
requestAnimationFrame: a throttle alternative. When your function recalculates and renders elements on screen and you want to guarantee smooth changes or animations. Note: no IE9 support.
requestAnimationFrame:一个节流的替代方案。当您的函数在屏幕上重新计算和渲染元素,并且您希望保证平滑的更改或动画时。注意:不支持IE9。
以上总结来自推荐阅读,再次强烈推荐阅读。