【问题标题】:Why requestAniamtionFrame doesn't cause stack overflow error?为什么 requestAnimationFrame 不会导致堆栈溢出错误?
【发布时间】:2021-08-27 18:59:49
【问题描述】:

我试图了解当递归调用 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. 浏览器看到空堆栈并将队列中的回调放入堆栈
  7. 重复

我假设requestAnimationFrame 做了类似不超过允许的堆栈大小的事情,但我不确定这是否就是全部。这是否也意味着只要我将堆栈大小保持在可接受的范围内,我就可以使用异步回调轰炸浏览器 API 而不会出现任何错误?

【问题讨论】:

  • 在所有同步执行完成之前不会运行。它安排给定的回调。它不是真正的递归,它看起来就是这样。这就是事件循环的本质。
  • @zero298 啊,有道理。如果您愿意,请发布答案,我会接受它

标签: javascript animation stack-overflow frame requestanimationframe


【解决方案1】:

requestAnimationFrame 在所有同步执行完成之前不会运行。它安排给定的回调。它的行为非常类似于setTimeout。它不是真正的递归,它看起来就是这样。这就是事件循环的本质。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 每秒 60 次*。这就是为什么我认为创建堆栈溢出是一种非常简单的方法,因为每秒一个调用会生成至少 60 个其他调用,这些调用可以非常快速地扩展。我认为@zero298 的评论解释了为什么没有堆栈溢出错误。
    猜你喜欢
    • 2011-10-22
    • 2014-12-20
    • 2011-02-08
    • 2021-01-26
    • 2019-12-08
    • 2018-07-01
    • 2010-09-11
    • 1970-01-01
    • 2011-01-13
    相关资源
    最近更新 更多