Alright, I did an experiment, and I'm really surprised at the results! Apparently, the logic (what would be drawSomething() in my previous example) is fired within the frame!!
So, let me show you my original method for starting an animation loop. I'm working on a 3D project at http://infamous.io. The Scene class (https://github.com/infamous/infamous/blob/master/src/motor/Scene.js) has a method for starting an animation loop the standard way: ```js async _startAnimationLoopWhenMounted() { this._animationLoopStarted = true if (!this._mounted) await this.mountPromise // So now we can render after the scene is mounted. const loop = timestamp => { this._inFrame = true this._runRenderTasks(timestamp) this._renderNodes(timestamp) // If any tasks are left to run, continue the animation loop. if (this._allRenderTasks.length) this._rAF = requestAnimationFrame(loop) else { this._rAF = null this._animationLoopStarted = false } this._inFrame = false } this._rAF = requestAnimationFrame(loop) } ``` Here's what the Chrome timeline shows for the logic that is fired inside the loop: https://cloud.githubusercontent.com/assets/297678/14764236/8eb72d4a-0965-11e6-9bb9-5db02cc23520.png Now, I went ahead and modified my Scene class so the method now looks like this: ```js function animationFrame() { let resolve = null const promise = new Promise(r => resolve = r) window.requestAnimationFrame(resolve) return promise } // ... async _startAnimationLoopWhenMounted() { this._animationLoopStarted = true if (!this._mounted) await this.mountPromise this._rAF = true let timestamp = null while (this._rAF) { timestamp = await animationFrame() this._inFrame = true this._runRenderTasks(timestamp) this._renderNodes(timestamp) // If any tasks are left to run, continue the animation loop. if (!this._allRenderTasks.length) { this._rAF = null this._animationLoopStarted = false } this._inFrame = false } } ``` And the timeline results are surprising! As you can see in the following screenshot, all of the logic happens within the frame (though you can see there's extra overhead from what I assume are the extra function calls due to the fact that I'm using Facebook Regenerator for the async functions): https://cloud.githubusercontent.com/assets/297678/14764237/8eb71ce2-0965-11e6-942a-3c556c48b9a0.png Near the bottom right of the screen shot, you can see the tooltip as I'm hovering on the call to `animationFrame` which returns the promise that I am awaiting in the loop. Although this behavior seems to be exactly what I was hoping for, it seems like there is something wrong. Could there be a bug in regenerator that is failing to defer my loop code to a following tick? Or is my code deferred to a following tick that somehow the animation frame knows to execute within the same tick? Maybe there's something I'm missing about the Promise API that allows for .then() of a promise (which I assume is what Regenerator is using) to be executed in the same tick? What's going on here? I was expecting to see the code of my loop execute outside of the "Animation Frame Fired" section. On Sat, Apr 23, 2016 at 6:28 AM, Boris Zbarsky <[email protected]> wrote: > On 4/23/16 4:09 AM, Salvador de la Puente González wrote: >> >> AFAIK, that should execute `drawSomething()` once per frame. Given a >> frame is each time the animatinFrame() promise resolves. > > > What's not obvious to me is whether it will execute it before the actual > paint for the frame (i.e. before or right after the loop that's notifying > the animation frame callbacks completes) or whether it will do > drawSomething() after the paint... > > -Boris > > _______________________________________________ > es-discuss mailing list > [email protected] > https://mail.mozilla.org/listinfo/es-discuss _______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

