节流不支持初次和最后触发模式,仅两种实现:时间戳版首次立即执行、后续按间隔执行;定时器版实为防抖,每次重置延时。需组合使用才能兼顾首尾触发。

节流本身不天然支持“初次触发”和“最后触发”两种模式——这是防抖的典型行为。节流的核心是“固定间隔执行一次”,它只有两种主流实现方式,行为不同,但都**不混合初/末次逻辑**。混淆这点,容易写出状态混乱、漏执行或误执行的代码。
时间戳版:首次触发立即执行,后续在间隔内忽略
适合 resize、scroll 等需要“至少每 X 毫秒响应一次”的场景。它靠记录上一次执行时间(lastTime)判断是否可执行:
- 第一次调用:now - lastTime(初始为 0)必然 ≥ delay,立刻执行,并更新 lastTime = now
- 后续调用:若距上次执行不足 delay,直接跳过;超过才执行并更新时间
- 不涉及定时器,无 clearTimeout,状态干净,不易出错
定时器版:首次触发设延时,重复触发会重置,最终只执行最后一次
注意:这其实是防抖(debounce)的行为,不是节流。但因常被误称为“节流”,需特别澄清:
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
- 每次触发都 clearTimeout 旧定时器,再 setTimeout 新的
- 函数体在 delay 后执行,且仅执行最后一次触发所设定的那个
- 适用于输入框搜索、按钮点击防重复等“停顿后才响应”的场景
- 若强行叫它“节流”,容易误导设计意图
想兼顾首次 + 最后?得组合,不能靠单个节流函数
真实业务中若需“首次立即执行 + 最后一次延迟补发”,应显式组合两个逻辑:
- 用时间戳版节流保证高频时稳定执行
- 额外加一个防抖逻辑监听“结束信号”(如 scroll 停止、input 失焦)
- 或用带 leading + trailing 参数的 debounce(如 Lodash 的 throttle 实际是 debounce 变种)
- 纯节流函数内部不做 trailing 补发,否则破坏“固定间隔”语义
关键提醒:别在时间戳版里加 clearTimeout
常见错误是把两种逻辑混写:
- 一边用 lastTime 判断时间差,一边又 clearTimeout 定时器
- 结果:timer 状态和 lastTime 不同步,导致该执行时不执行,或不该执行时多执行
- 选一种范式就坚持到底:时间戳版管“间隔控制”,定时器版管“延迟收尾”










