为什么 requestAniamtionFrame 不会导致堆栈溢出错误?



我试图理解当递归地调用requestAnimationFrame()时,浏览器的底层发生了什么。

我在浏览器控制台中运行了这样的代码:

function foo(){
requestAnimationFrame(foo);
console.log("foo");
}
foo()

结果:"foo"正在不停地打印。

我的问题:我不明白为什么我没有超过允许的堆栈大小。

我认为发生了什么:

function callAsynchronously(callback){
setTimeout(callback, 1);
}
function foobar(){
callAsynchronously(foobar); // replacement for requestAnimationFrame
console.log("hi");
}
foobar() // result is the same as before, non-stop printing

上面的代码是我如何可视化requestAnimationFrame:

  1. foobar()被放到堆栈
  2. callAsynchronously(foobar)被放到堆栈
  3. callAsynchronously(foobar)从栈中弹出
  4. console.log("hi")被放到堆栈/浏览器api在setTimeout完成后将foobar回调到某个队列
  5. console.log("hi")从栈中弹出
  6. 浏览器看到空堆栈并将队列中的回调放到堆栈

我假设requestAnimationFrame做了一些类似于不超过允许的堆栈大小的事情,但我不确定这是否就是它的全部。这也意味着我可以轰炸浏览器api与异步回调没有得到任何错误,只要我保持我的堆栈大小在可接受的范围内?

requestAnimationFrame在所有同步执行完成之前不会运行。它调度给定的回调。它的行为很像setTimeout。它不是真正的递归,只是看起来是这样。这就是事件循环的本质。

根据设备屏幕的刷新率调用requestAnimationFrame。例如,如果你在60hz屏幕上观看,foo函数将被调用60次。

最新更新