是什么让循环的其余部分执行,然后requestAnimationFrame执行下一帧?
我误解了这种方法是如何工作的,并且无法在任何地方看到明确的解释。我尝试在这里阅读时间规范http://www.w3.org/TR/animation-timing/,但我无法弄清楚它是如何工作的。
编辑:
例如,此代码取自threejs文档。
var render = function () {
requestAnimationFrame(render);
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
答案 0 :(得分:11)
如果我完全偏离基地,请告诉我。我之前没有使用动画的东西。我看到使用requestAnimationFrame
的一个例子是:
(function animloop(){
requestAnimFrame(animloop);
render();
})();
您是否想知道为什么animloop
被传递到requestAnimFrame
时,在随后被调用时不会导致无限循环?
这是因为此函数不是真正的递归。您可能会认为在致电animloop
时会立即调用requestAnimFrame
。不是这样! requestAnimFrame
是异步的。因此,语句按您看到的顺序执行。这意味着主线程没有等待来调用requestAnimFrame
来回复,之后调用render()
。所以render()
几乎立即被召唤。但是回调(在本例中为animloop
)是不是立即调用。当您已经退出第一次对animloop
的调用时,可能会在以后的某个时间点被调用。这个对animloop
的新调用有自己的上下文和堆栈,因为它实际上没有从在第一个animloop
调用的执行上下文中调用。这就是为什么你最终没有无限递归和堆栈溢出。
答案 1 :(得分:5)
这就是:
你声明一个函数定义,调用requestAnimationFrame
函数。
计划您的函数在时间正确时再次被调用和执行,这通常是在16ms之后的下一帧。此外,此调度是异步的。它不会停止在它下面执行代码。因此,直到16ms过去,这条线下面的代码才会起作用。
但是,在大多数情况下,功能会在3-4毫秒内执行。
但是如果函数需要更长时间才能完成,那么下一帧将被延迟,从而不会执行计划任务,即再次调用相同的函数。
从某种意义上说,动画是无限循环。 requestAnimationFrame的目标是什么。但是,此非阻塞无限循环受帧/ fps 的限制。
答案 2 :(得分:1)
出于同样的原因,在循环中使用setTimeout
调度回调不会导致无限递归,计划对 JS event loop >而不是立即执行。
调用不是在当前上下文中进行的,因此从严格意义上讲,它在技术上不是递归,并且不会导致堆栈限制超出错误。
此图表适用于Dart,但JS中的概念相同。如果您有兴趣阅读有关事件循环,调度计时器以及微任务和宏任务之间差异的更多信息,请查看this question。