节流是限制函数在单位时间内最多执行一次,用于解决鼠标移动等高频事件导致的性能问题;其原理是通过时间戳比较间隔,确保首次立即执行且不补调用尾部,兼顾流畅性与性能。

节流(Throttle)是解决鼠标移动(mousemove)事件高频触发导致性能问题的常用手段——它能限制函数在单位时间内最多执行一次,既保留关键轨迹采样,又避免 CPU 过载或渲染卡顿。
为什么鼠标移动必须节流?
用户快速移动鼠标时,mousemove 每秒可能触发 60–120 次(甚至更高),若每次回调都做计算、DOM 更新或 Canvas 绘图,会迅速堆积任务,造成页面掉帧、响应延迟。节流不是“丢弃所有中间点”,而是有节奏地保留代表性坐标,兼顾流畅性与性能。
手写一个可靠节流函数(带时间戳 + 尾调用)
推荐使用「时间戳 + 最后执行时间」方式,比定时器更精准,且支持立即触发首帧:
function throttle(func, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
func.apply(this, args);
lastTime = now;
}
};
}使用示例:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
let lastX = 0, lastY = 0;
<p>const drawLine = (x, y) => {
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(x, y);
ctx.stroke();
lastX = x; lastY = y;
};</p><p>// 节流到 16ms(约 60fps)
const throttledDraw = throttle(drawLine, 16);</p><p>canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
throttledDraw(x, y);
});</p>注意边界:是否需要“首次立即执行”和“结束补发”?
对鼠标轨迹这类连续行为,通常不需要尾部补调用(即“trailing”),因为轨迹终点由 mouseup 或 mouseleave 明确界定;但首帧立即执行很重要——否则鼠标刚一动就延迟 16ms,手感明显滞后。上面实现已满足该要求。
如果后续需兼容拖拽结束时的收尾绘制(比如画个终点圆点),可单独监听 mouseup 并调用一次原函数。
现代替代方案:requestAnimationFrame(rAF)更顺滑
对视觉反馈要求高的轨迹绘制(如手写、白板),用 requestAnimationFrame 替代固定毫秒节流更优——它自动对齐屏幕刷新率,且空闲时不会强制执行:
let pending = false;
let latestX, latestY;
<p>function drawAtNextFrame(x, y) {
latestX = x;
latestY = y;
if (!pending) {
pending = true;
requestAnimationFrame(() => {
drawLine(latestX, latestY); // 实际绘制
pending = false;
});
}
}</p><p>canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
drawAtNextFrame(x, y);
});</p>rAF 方案天然限频于屏幕刷新率(通常 60fps),不依赖手动设 delay,也避免时间戳计算开销,更适合动画类轨迹场景。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










