我试图理解当递归地调用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
:
foobar()
被放到堆栈callAsynchronously(foobar)
被放到堆栈callAsynchronously(foobar)
从栈中弹出console.log("hi")
被放到堆栈/浏览器api在setTimeout
完成后将foobar
回调到某个队列console.log("hi")
从栈中弹出- 浏览器看到空堆栈并将队列中的回调放到堆栈
我假设requestAnimationFrame
做了一些类似于不超过允许的堆栈大小的事情,但我不确定这是否就是它的全部。这也意味着我可以轰炸浏览器api与异步回调没有得到任何错误,只要我保持我的堆栈大小在可接受的范围内?
requestAnimationFrame
在所有同步执行完成之前不会运行。它调度给定的回调。它的行为很像setTimeout
。它不是真正的递归,只是看起来是这样。这就是事件循环的本质。
根据设备屏幕的刷新率调用requestAnimationFrame
。例如,如果你在60hz屏幕上观看,foo
函数将被调用60次。