节流函数用于限制视频timeupdate事件频率以避免ui卡顿,核心是按固定间隔(如100ms)执行更新逻辑;可手写闭包实现,或结合requestanimationframe提升渲染一致性,并需处理duration无效、seeked等边界情况。

节流函数在视频时间轴同步中主要用于限制 timeupdate 事件的触发频率,避免高频回调导致 UI 卡顿或重复渲染。核心思路是:只让时间更新逻辑每隔固定间隔(如 100ms)执行一次,而非每次毫秒级变化都响应。
为什么视频 timeupdate 需要节流
浏览器对 timeupdate 事件的触发非常频繁(通常每 20–250ms 一次,取决于视频编码和浏览器),直接绑定更新进度条、时间文本等操作会造成:
- 短时间内大量 DOM 操作,拖慢渲染帧率
- 重复计算(如反复调用
Math.floor(video.currentTime))无实际意义 - 与后端同步或日志上报时,产生冗余请求
手写一个轻量节流函数用于时间同步
不依赖 Lodash,用闭包 + 时间戳控制即可:
function throttle(func, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
func.apply(this, args);
lastTime = now;
}
};
}
使用示例:
const video = document.getElementById('myVideo');
const progressBar = document.getElementById('progress');
<p>// 节流后的时间更新处理
const throttledUpdate = throttle(() => {
const percent = (video.currentTime / video.duration) * 100;
progressBar.style.width = <code>${Math.min(100, percent)}%</code>;
document.getElementById('currentTime').textContent = formatTime(video.currentTime);
}, 100); // 每 100ms 最多更新一次</p><p>video.addEventListener('timeupdate', throttledUpdate);
</p>
更稳妥的做法:结合 requestAnimationFrame
如果追求更高渲染一致性(尤其动画平滑性),可将节流逻辑与 requestAnimationFrame 结合,确保更新在下一帧执行且不丢帧:
function throttleRAF(func) {
let isQueued = false;
return function(...args) {
if (!isQueued) {
isQueued = true;
requestAnimationFrame(() => {
func.apply(this, args);
isQueued = false;
});
}
};
}
<p>const rafThrottled = throttleRAF(() => {
progressBar.style.width = <code>${(video.currentTime / video.duration) * 100}%</code>;
});
video.addEventListener('timeupdate', rafThrottled);
</p>
这种方式天然匹配浏览器刷新节奏(约 60fps),比固定毫秒节流更契合渲染管线。
注意边界情况
节流不能替代必要的状态校验:
- 视频加载未完成时
duration可能为NaN或Inf,需先判断isFinite(video.duration) - 用户拖动进度条会触发
seeking和seeked,此时应立即更新 UI,可额外监听seeked并取消节流延迟(或单独处理) - 暂停/播放切换时,
timeupdate会停止,无需额外干预,但若做播放历史记录,建议在pause和ended时补发最终时间点
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











