节流(throttle)首尾兼顾的实现需结合时间戳与定时器:首次触发立即执行,末次触发由定时器兜底。核心是维护lasttime和timer双状态,通过时间差判断即时执行,否则重置定时器确保末次不丢失。

节流(Throttle)的核心目标是控制函数执行频率,避免高频触发(如 scroll、resize)导致性能问题。要实现“首尾兼顾”——即首次触发立即执行,末次触发也必须执行(而不是被丢弃),仅靠纯时间戳或纯定时器都不够:时间戳方案会丢失最后一次;定时器方案(只用 setTimeout)通常首次不执行、末次也不保证执行。真正可行的方式是将两者结合,用时间戳判断是否该立即执行首次,再用定时器兜底保障末次。
核心思路:双状态 + 双机制
维护两个关键信息:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 上一次执行的时间戳(lastTime)
- 正在等待执行的定时器 ID(timer)
每次触发时:先检查距上次执行是否已超间隔;若是,立即执行并更新 lastTime;否则,若无 pending 定时器,则设置一个延迟执行的定时器(确保末次能跑)。定时器回调中清空 timer,并执行函数(此时它代表“窗口内最后一次”)。
代码实现(首尾兼顾版)
以下是可直接使用的标准实现:
function throttle(func, delay) {
let lastTime = 0;
let timer = null;
<p>return function (...args) {
const now = Date.now();
// ✅ 首次或超过 delay:立即执行
if (now - lastTime >= delay) {
func.apply(this, args);
lastTime = now;
} else {
// ❌ 未到间隔,但需确保末次执行 → 启动/重置定时器
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
lastTime = Date.now(); // 更新为定时器执行时刻
timer = null;
}, delay - (now - lastTime)); // 精确补足剩余时间(更平滑)
}
};
}</p>为什么这样能兼顾首尾?
- 首次触发:lastTime 初始为 0,now - 0 > delay(除非 delay 是 0),立即执行 ✔️
- 连续高频触发:中间多次走 else 分支,不断 clearTimeout + 重设 timer,只保留最后一次的延时计划 ✔️
- 末次触发后 delay 时间内无新触发:定时器自然执行,完成兜底 ✔️
- 末次触发紧邻上一次:仍会重设 timer,确保它在“本次触发之后 delay 毫秒”执行,不丢失 ✔️
使用注意与优化点
- 推荐用
Date.now()而非new Date().getTime(),更轻量 - 定时器延迟设为
delay - (now - lastTime),比固定delay更精准,避免执行堆积 - 若需取消节流函数,可返回一个 cancel 方法(扩展版常见)
- 注意 this 和参数透传:使用
func.apply(this, args)或箭头函数 +...args保证上下文正确
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










