节流函数默认不保证最后一次执行,与防抖本质不同;标准节流仅确保单位时间最多执行一次,若末次触发未达条件则被丢弃,需通过尾部标记、flush方法或事件生命周期配合实现兜底执行。

你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
时间戳 + 尾部标记(推荐)
在记录上次执行时间的基础上,增加一个标志位标记“是否有待执行的调用”。当新调用到来时:
- 如果距离上次执行 ≥ 间隔,立即执行,并更新时间戳
- 否则,缓存当前参数和 this,并设 pending = true
- 在每次执行后,启动一个延迟任务:若 pending 为 true,则清空 pending 并执行缓存的调用
定时器版 + 清理钩子(兼容性好)
使用定时器控制节流窗口,同时在返回函数中监听“是否即将结束调用流”:
- 每次调用都尝试设置一个延迟为 delay 的定时器
- 若已有定时器,先 clearTimeout,再重设
- 关键点:在 setTimeout 回调里执行函数后,**再设一个更短的“兜底定时器”(如 delay / 3)用于捕获终止信号**;或更稳妥地,在函数返回前注册一个 once 类型的清理回调(如 onLastCall)
throttledResize.flush()。
为什么不能靠 setTimeout 自动保障?
单纯依赖 setTimeout 的节流实现(如“有 timer 就 return,没有就 set”)天然存在执行盲区:
- 用户快速滚动 5 次,第 5 次触发时 timer 还在运行 → 被忽略
- 滚动结束后 timer 执行了第 4 次,但第 5 次从未进入队列 → 丢失
- 没有外部干预机制,JS 无法感知“事件流已终止”

















