JavaScript 事件循环进阶:requestAnimationFrame 与 Web Workers
在浏览器中,如何实现丝滑流畅的 60fps 动画?如何在单线程 JavaScript 环境中实现真正的并行计算?理解事件循环的高阶应用是构建高性能 Web 应用的关键。
前言:从 60fps 的动画说起
在 JavaScript 中,常见的动画实现方式主要有三种。虽然它们都能产生运动效果,但在性能表现和用户体验上差异巨大。
使用 setInterval(不推荐)
function animateWithSetInterval() {
setInterval(() => {
updateAnimation();
renderFrame();
}, 16.67);
}
上述代码试图达到 60fps(1000/60 ≈ 16.67ms),但定时器并不精确。如果主线程繁忙,回调可能会延迟执行,导致丢帧或过度绘制,造成卡顿。
递归 setTimeout
function animateWithSetTimeout() {
function loop() {
updateAnimation();
renderFrame();
setTimeout(loop, 16.67);
}
loop();
}
这种方式比 setInterval 稍好,因为它允许动态调整间隔,但仍可能和屏幕刷新不同步。浏览器无法优化这种模式,且随着嵌套加深,栈空间也可能成为隐患。
使用 requestAnimationFrame(推荐)
function animateWithRAF() {
function loop(timestamp) {
updateAnimation(timestamp);
renderFrame();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}
这是目前的标准做法。它的优势在于自动匹配屏幕刷新率,节省资源,并且浏览器可以在页面不可见时暂停调用,避免无效计算。

