BetaThis is a live doc! Anyone with edit access can make updates in real time without having to publish.
By Bryan
尽管 Throttle / Debounce 在前端领域用的比较多且本文也用了 JS 举例,但是实际上这个术语是通用的,后端等也会使用
核心区别
Debounce:在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新从新的时间开始计时 n 秒,直至连续的 n 秒没有新的触发事件发生时才会执行回调
immediate = true:在首次触发事件时立刻执行回调一次
Throttle:在事件被首次触发时立刻执行回调,后续的 n 秒出现新的事件时直接忽略
应用场景
基于用户输入进行实时展示:debounce
防止用户连续点击按钮触发多个事件:throttle
滚动事件处理:throttle
实现代码(以 JS 为例)
Throttle
function throttle(fn, delay) {
let lastTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
};
}Debounce
function debounce(fn, delay, immediate = false) {
let timer = null;
return function (...args) {
const callNow = immediate && !timer;
clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
if (!immediate) {
fn.apply(this, args);
}
}, delay);
if (callNow) {
fn.apply(this, args);
}
};
}如果始终 immediate=false,可以简化
function throttle(fn, delay) {
let timer = null;
return function (...args) {
if (timer) {
return;
}
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
};
}如果始终 immediate=true,可以简化
function throttle(fn, delay) {
let timer = null;
return function (...args) {
if (timer) {
return;
}
fn.apply(this, args);
timer = setTimeout(() => {
timer = null;
}, delay);
};
}
补充
throttle 和 debounce(immediate=true) 有什么区别?
二者同样会立刻执行,但是在连续不停触发事件时候,throttle 保证了每隔单位时间都会触发一次,而 debounce(immediate=true) 则在后续不会再触发事件
假设 delay = 1000ms,持续触发事件:
throttle:
时间轴: 0ms 1000ms 2000ms 3000ms
执行: 执行 执行 执行 执行
事件: | | | | | | | | | | | | | | | |
debounce(immediate=true):
时间轴: 0ms 1000ms 2000ms 3000ms
执行: 执行 (无) (无) (无)
事件: | | | | | | | | | | | | | | | |
↑
第一次执行后,后续的触发都被忽略,直到停止触发并等待1000ms后再触发新事件才会执行