节流是“固定时间窗口内最多执行一次”,适用于resize、mousemove、scroll等高频非实时场景;核心用setTimeout加状态标记实现首次触发立即执行、之后每delay毫秒最多执行一次。

节流(throttle)不是“限制调用次数”,而是“固定时间窗口内最多执行一次”。它适合处理高频触发但不需要实时响应的场景,比如窗口 resize、鼠标 mousemove、滚动 scroll 事件。
节流函数的核心逻辑:定时器 + 状态标记
最常用且易理解的实现基于 setTimeout 和一个布尔标记。关键在于:触发时若未处于“等待执行”状态,就立即执行并设为“等待中”;否则只更新待执行的参数(如有),不重复设定时器。
- 每次调用先检查
isThrottling标志位,为 false 才进入执行流程 - 执行后立刻设
isThrottling = true,并在定时器回调里重置它 - 如果在等待期间又被调用,不新建定时器,只缓存最新参数(可选)
- 注意:必须在定时器回调中重置标志位,不能在执行函数末尾——否则无法拦截后续调用
function throttle(fn, delay) {
let isThrottling = false;
return function(...args) {
if (isThrottling) return;
fn(...args);
isThrottling = true;
setTimeout(() => {
isThrottling = false;
}, delay);
};
}
为什么不用 setInterval 或直接 clearTimeout 重置?
用 setInterval 实现节流会失去触发时机控制——它不管有没有新事件,只按固定节奏跑;而真实节流应“首次触发立刻执行,之后每 delay 毫秒最多再执行一次”。直接 clearTimeout 重置旧定时器(即“防抖式节流”)会导致行为漂移:可能永远等不到执行,尤其在持续高频触发时。
-
setInterval方案无法响应“第一次触发就执行”的需求 - 仅靠
clearTimeout+ 新setTimeout,实际退化成防抖(debounce),不是节流 - 标准节流必须保有“立即执行 + 延迟锁定”双阶段,缺一不可
带 leading / trailing 控制的节流(Lodash 风格)
原生节流常需支持“首次触发是否立即执行(leading)”和“停止触发后是否补最后一次(trailing)”。这需要额外维护上次执行时间戳和一个延迟执行的定时器。
php配置文件php.ini的中文注释版是一本由多位作者编著的有关PHP内部实现的开源书籍。从环境准备到代码实现,从实现过程到细节延展,从变量、函数、对象到内存、Zend虚拟机…… 如此种种,道尽PHP之风流。
立即学习“Java免费学习笔记(深入)”;
-
leading: true表示第一次调用立刻执行,之后进入冷却 -
trailing: true表示冷却期结束后,若期间有新调用,则再执行一次(需记录最后参数) - 两者同时为
true时,要注意避免重复执行——常见做法是用时间戳判断是否已过 delay,而非仅依赖标志位 - Lodash 的
throttle默认leading=true、trailing=true,但实际项目中多数场景只需leading=true
节流真正难的不是写出来,而是判断该不该用——比如搜索框输入,用节流反而卡顿,该用防抖;而 canvas 绘图跟随鼠标移动,漏掉中间几帧没关系,节流就比防抖更合适。别光抄代码,先想清楚事件频率和用户感知之间的关系。










