为什么在循环开始时调用 requestAnimationFrame 不会导致无限递归?

问题描述:

是什么让循环的其余部分执行,然后 requestAnimationFrame 执行下一帧?

What is going on that allows the rest of the loop to execute, and then for requestAnimationFrame to execute next frame?

我误解了这种方法的工作原理,并且在任何地方都看不到明确的解释.我试着在这里阅读时间规范 http://www.w3.org/TR/animation-时间/,但我无法弄清楚它是如何工作的.

I am misunderstanding how this method works, and can't see a clear explanation anywhere. I tried reading the timing specification here http://www.w3.org/TR/animation-timing/ but I couldn't make out how it worked.

例如,此代码取自threejs文档.

For example, this code is taken from the threejs documentation.

var render = function () { 
  requestAnimationFrame(render); 
  cube.rotation.x += 0.1; 
  cube.rotation.y += 0.1;
  renderer.render(scene, camera); 
};

如果我完全不在基地,请告诉我;我以前没用过动画的东西.我看到的一个使用 requestAnimationFrame 的例子是:

Please let me know if I am completely off-base; I haven't used the animation stuff before. An example I saw for using requestAnimationFrame is:

(function animloop(){
  requestAnimFrame(animloop);
  render();
})();

您是否想知道为什么 animloop 在传入 requestAnimFrame 时不会在随后被调用时导致无限循环?

Are you wondering why animloop as it is passed into requestAnimFrame doesn't cause an infinite loop when it is subsequently called?

这是因为这个函数不是真正递归的.您可能认为在调用 requestAnimFrame 时会立即调用 animloop.不是这样!requestAnimFrame 是异步的.所以语句按照你看到的顺序执行.这意味着主线程不会等待requestAnimFrame的调用返回,render()的调用之前代码>.所以 render() 几乎立即被调用.然而,回调(在本例中为 animloop)不会立即调用.当您已经退​​出对 animloop第一次调用时,它可能在将来的某个时刻被调用.这个对 animloop 的新调用有自己的上下文和堆栈,因为它实际上并没有从第一个 animloop 调用的执行上下文被调用.这就是为什么您不会以无限递归和堆栈溢出结束的原因.

This is because this function isn't truly recursive. You might be thinking that animloop is immediately called when you call requestAnimFrame. Not so! requestAnimFrame is asynchronous. So the statements are executed in the order that you see. What this means is that the main thread does not wait for the call to requestAnimFrame to return, before the call to render(). So render() is called almost immediately. However the callback (which in this case is animloop) is not called immediately. It may be called at some point in the future when you have already exited from the first call to animloop. This new call to animloop has its own context and stack since it hasn't been actually called from within the execution context of the first animloop call. This is why you don't end up with infinite recursion and a stack overflow.