3

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

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

4

2 回答 2

1

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

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

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

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

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

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

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

于 2013-06-19T00:47:13.160 回答
0

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

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

于 2013-06-18T22:34:33.597 回答