JavaScript无法提供真正实时保障,应优先用requestAnimationFrame处理视频帧、AudioWorklet处理音频块,避免setTimeout驱动主循环,微任务仅用于轻量状态同步。

优先使用 requestAnimationFrame 处理视频帧
对于页面内视频渲染、Canvas 绘图、WebGL 帧更新等视觉任务,requestAnimationFrame(rAF)是唯一被浏览器保证与屏幕刷新率同步的宏任务入口。它不是普通定时器,而是由浏览器在下一帧绘制前主动调度,通常为 60fps(约 16.7ms 间隔),且会自动节流(如标签页后台时暂停)。
用法示例:
- 在 rAF 回调中读取
videoElement.currentTime,计算当前帧位置 - 用
canvas.getContext('2d').drawImage(video, ...)捕获并处理帧 - 避免在 rAF 中做重计算;耗时操作应拆分或移交 Web Worker
用 AudioContext 和 onaudioprocess 实现音频实时调度
Web Audio API 的 AudioContext 是浏览器提供的低延迟音频处理核心。其 ScriptProcessorNode 已废弃,但现代方案是:
- 使用
AudioWorklet(需注册 worklet module):每个音频块(通常 128 或 256 样本)触发一次process()方法,运行在独立线程,延迟可压至几毫秒 -
AudioWorklet的process()是浏览器内核级调度的“准实时宏任务”,不经过 JS 主线程事件循环,因此不受宏/微任务队列阻塞影响 - 若必须在主线程协调(如响应 UI 控制),可用
port.postMessage()发送轻量指令,配合requestIdleCallback或setTimeout(..., 0)做非关键同步
避免 setTimeout/setInterval 驱动音视频主循环
setTimeout(..., 0) 不等于“立即执行”,实际延迟常 ≥4ms,且受主线程负载影响剧烈。连续用它做帧调度会导致:
立即学习“Java免费学习笔记(深入)”;
- 帧率抖动(jank)、音画不同步(AV sync drift)
- 多个定时器相互抢占,无法保证执行顺序或间隔精度
- 与用户交互、网络请求等其他宏任务竞争,加剧不确定性
替代方案:
- 视频:始终以
video.requestVideoFrameCallback()(Chrome 114+)替代 rAF,它专为视频帧精确回调设计,精度更高 - 音频:完全交由
AudioWorklet或WebAssembly + OfflineAudioContext批处理 - 通用时间轴控制:用
performance.now()做高精度时间测量,结合自适应步进逻辑,而非依赖定时器唤醒
微任务仅用于状态同步,不用于实时驱动
微任务(如 Promise.then、queueMicrotask)在当前宏任务结束后立刻执行,**适合做轻量、确定性的状态同步**,例如:
- 在 rAF 或 AudioWorklet 处理完一帧后,用
queueMicrotask(() => updateUIState())更新进度条、时间戳等 DOM - 确保多个异步操作(如加载元数据、初始化解码器)完成后再启动播放,避免 race condition
- 但绝不可用微任务来“插入”音视频处理逻辑——它不触发渲染、不调度音频块、无法控制执行时机


















