【问题标题】:What browser-internal operations prevent requestAnimationFrame from being invoked?哪些浏览器内部操作会阻止调用 requestAnimationFrame?
【发布时间】:2013-06-19 08:55:20
【问题描述】:

我知道这个问题的答案是特定于浏览器(甚至浏览器版本)的,但我希望可能有一些通用规则或行为适用于所有地方。

我知道我的 JavaScript 在 requestAnimationFrame 回调中的执行时间会减慢调用速度。但是我的代码影响但不一定控制的其他浏览器活动呢?在随后调用 requestAnimationFrame 回调之前,我的 DOM 更改引起的所有回流和布局和绘画活动是否同步发生?还是有可能在先前更改的像素出现在屏幕上之前调用下一个回调?

【问题讨论】:

  • 首先想到的是垃圾收集器,磁盘/网络访问以及 cpu/gpu 峰值也可能导致此问题

标签: javascript html performance dom cross-browser


【解决方案1】:

通常情况下,浏览器需要做的所有事情,重绘,处理 setTimeout 和 setInterval 都是作为事件放入事件队列中并一一执行。

requestAnimationFrame 是一种特殊情况,因为它会同步到显示器上的 VBLANK 间隙,这意味着当 VBLANK 发生时将调用回调。

正如怪诞在他的回答中所说,Javascript 是单线程的,因此是事件队列,但在这种情况下,浏览器会强制一个事件向前(先于当前队列)。

回调时发生的确切情况是,当前绘制到画布的所有内容都被“blitted”到浏览器的位图(您在屏幕上看到的),然后继续执行该函数。无论其他事件的结果是什么,此时也会更新(即使它们正在进行中 - 在内部,一个元素被处理为它自己的位图,然后作为画布元素 IIRC 绘制到屏幕上)。

即使回调在它应该发生的时候发生并不意味着例如在回调函数本身的调用之间不能发生绘制事件。这当然会影响性能。

接下来是从第 0 帧到第 1 帧的时间预算,通常约为 16.7 毫秒(@ 60Hz)。如果您的任务未在此预算内完成,则不会发生任何事情,但是当您调用 requestAnimationFrame 时,它不会回调,直到下一次 VBLANK 发生(“跳过心跳”),您会在动画中注意到这一点(正如您将与 setTimeout/setInternval 一起查看,因为它们不同步到 VBLANK,并且会不时在更新之间出现导致抖动 - 这是 requestAnimationFrame 与其更底层的结构一起提供的主要原因,这使得它更高效本身)。

@ 987654324@回调率降低到一半(似乎在浏览器上是一致的),当TAB不活动时(或者如果有硬件限制或在电池上运行)。不同之处在于,现在事件不是每 ~16.7 ms 强制执行一次,而是在 ~33.4 ms 时执行,并且其他事件像以前一样执行(重新绘制等)(不确定供应商是否普遍采用了事件队列的减速)。

【讨论】:

    【解决方案2】:

    JavaScript(在浏览器中)是单线程的,所以一切都是按顺序发生的。从这个角度来看,一切都会影响一切。但只要这些操作花费的时间少于一帧(希望他们会这样做),您就不必担心。

    其中一个好处是您不必担心同步问题。在上一个回调完成所有它必须做的事情之前,下一个调用不会发生。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-14
      • 1970-01-01
      • 2010-09-20
      • 1970-01-01
      • 2011-05-20
      • 2012-04-16
      • 2013-07-03
      • 1970-01-01
      相关资源
      最近更新 更多