有没有 setTimeout(.., 0) 比 requestAnimationFrame() 更好的情况?

Vla*_*lad 11 javascript browser

我一直在使用setTimeout(function(){ ... }, 0)一种方法将函数调用延迟一个刻度。

通常,当我尝试直接操作事件循环以确保事物按特定顺序执行时,我一直在使用此方法,并且在大多数情况下它与 UI 相关。

有时我能感觉到那个“滴答”,尤其是当我使用它在一个元素上运行一些 3rd 方 JS 库时。

但我最近发现requestAnimationFrame。这几乎实现了同样的事情,但以更优雅的方式。

现在我很好奇,是否有任何地方它更利于使用的情况下,setTimeout(function(){ ... }, 0)requestAnimationFrame(function(){ ... })

小智 5

它们不是同一件事。

调用自身的函数setTimeout(fn, 0)将尽可能频繁地运行。

调用自身的函数requestAnimationFrame(fn)将每帧调用一次——通常每秒 60 次。顾名思义,它适用于动画,在动画中,更新页面状态的频率超过其显示的频率是没有意义的。

  • @Ploppy 不,我知道我在说什么。请注意“使用……调用自身”的语言。 (6认同)
  • 好吧,我现在明白了,这很令人困惑,因为你正在谈论函数递归调用自身的特定情况。抱歉,-1,我的错。 (3认同)

Set*_*ite 2

来自https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame

我看到的唯一危险信号是这个人:

在后台选项卡或隐藏 iframe 中运行时,回调速率可能会降低至较低速率,以提高性能和电池寿命。

但我相信只有当 requestAnimationFrame 递归调用自身时才会发生这种情况。

因此,如果您有一些使用 requestAnimationFrame 的长时间运行的代码,如果用户不在该选项卡上,则可能需要更长的时间。除此之外,您正在使用一个函数来做一些它从未打算做的事情,但是 setTimeout 并不是被设计为跳过一个刻度的方式,所以......

作为一个建议:一般来说,我发现你通常可以通过正确使用承诺等来避免 setTimeout 技巧。但我发现了一些案例,尤其是。当使用 Angular 1.x 时,我找不到比使用它更好的解决方案。

有趣的花絮。通过简单的性能测试,requestAnimationFrame 似乎明显更快:

console.time()
for(let i = 0; i < 100000; i++){
  requestAnimationFrame(() => {(5*5*77/3)*88});
}
console.timeEnd()
Run Code Online (Sandbox Code Playgroud)

大约 80 毫秒(在我的电脑上)

console.time()
for(let i = 0; i < 100000; i++){
  setTimeout(() => {(5*5*77/3)*88}, 0);
}
console.timeEnd()
Run Code Online (Sandbox Code Playgroud)

得到约 225 毫秒(在我的电脑上)