BetaThis is a live doc! Anyone with edit access can make updates in real time without having to publish.
尽管 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后再触发新事件才会执行