我们可以将requestAnimFrame视为应用程序循环上的'yield'以允许事件循环处理吗?
-
21-12-2019 - |
题
我正在使用 requestAnimFrame
方法 在JavaScript中使我的画布在我的程序的主循环中更新:
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
function animate() {
requestAnimationFrame( animate );
//var runcount = 100;
//for (var i=0;i<=100;i++) {
draw();
// if (runcount === i)
// alert("Completed program loop");
// }
}
发生的事情是这样的 我的程序在我的主循环运行了100之后才更新了画布 迭代,然后停止。在我添加 上面的方法进入我的主循环,突然我得到画布更新 在我的程序的每个循环中。
在我的程序完成之前画布没有得到更新的事实让我认为画布更新是在一个没有得到优先权的不同线程中运行的。(但我们知道 JavaScript是单线程的).
我的问题是 - 我们可以将requestAnimFrame视为应用程序循环上的'yield'以允许事件循环处理吗? 我仍然可以假设JavaScript是单线程的吗?
解决方案
你不是具体的关于你是如何做你的迭代1000次,但我会假设你的意思是你使用一个迭代 for
或 while
循环(?如果我错了,请纠正我。.).
当您执行for/while循环时,脚本将忙于循环,直到该循环(或范围)完成。正如你所知道的那样,JS是单线程的,它在执行此操作时无法处理事件队列等事情-因此没有任何东西可以更新(包括。DOM)直到循环完成(一般来说,如果DOM更新在单独的线程上运行,可能会有浏览器特定的实现允许DOM更新,例如,但这是与JS分开的事情)。
现在你实现了rAF,你正在做一个单一的迭代。 框架.这意味着浏览器有时间处理事件队列 异步 (与多线程不同),除非您在循环中处理的代码也忙循环一段时间,这将创建与第一个相同的场景。
你本可以用的 setTimeout
""好吧。RAF做什么不同于例如 setTimeout
或 setInterval
这是一个高效的低级别实现定时器机制,能够同步到监视器的 VBLANK的 周期(视频卡通过一个称为vsync的选项从垂直消隐)--用简单的词来说,这意味着显示器的刷新率(通常为60赫兹)。这允许我们创建平滑(er)动画,这就是为什么它被称为请求*动画*框架,因为这是它的主要用途。
JS还是单线程的吗?是的,这不会改变(在JS中实现多线程的唯一方法是使用Web Workers)。
RAF有什么改变吗?不是在这个领域-这是一个更准确和性能的替代 setTimeout
它以不同的方式同步,但仅此而已。它将受到与之相同的限制 setTimeout
不能够触发,如果一个范围是忙(因此 request
*名称的一部分,这意味着没有保证),但是当它触发时,它将与监视器刷新率同步。