Request animation frame called constantly
Asked Answered
D

2

13

Trying to understand RequestAnimationFrame and how it works internally.

Browser has a main thread which is an event loop. The event loop can be populated with various asynchronous events like user interaction, timers getting fired, network calls completing and events triggering layout and painting e.g. input or JS.

So, when a JS function invalidates the layout of the DOM or causes repaint, the browser's main thread repaints the layers that need updating and the compositor thread uploads the updated textures to the GPU where final compositing occurs and the resulting image is displayed onto the screen.

So, I have the impression that browsers only perform paint when actually required. If you capture events on Chrome Dev Tools timeline on a static page with nothing happening, absolutely no events are captured (no layout, no paint, no animation frame fired). Makes sense.

But then you run the following code on the console,

function onBeforeNextRepaint() {
    requestAnimationFrame(onBeforeNextRepaint);

    console.log('About to paint ...');
}

onBeforeNextRepaint();

Now, you capture the timeline events again and you notice the 'Animation Frame Fired' events and your console gets logged with 'About to paint ...'.

onBeforeNextRepaint gets called

Animation Frame Fired invoked

According to MDN,

The Window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint.

That means the browser is constantly painting and therefore calling my function to log the message before each repaint. I am guessing the browsers maintain a scheduler that makes the paint calls at the rate that matches the refresh rate of the screen.

Now my confusion lies on the following:

  1. Is the browser's main thread constantly repainting, generating textures and uploading textures to the GPU and making draw calls (throttled to match the refresh rate of the screen)? (Sounds inefficient)
  2. Is that the reason why my 'onBeforeNextRepaint' callback gets called constantly?
  3. If 1 and 2 are true, on my first timeline capture, why do i not capture 'Update Layer Trees' and 'Composite Layers' events?
Dichromate answered 21/2, 2015 at 18:41 Comment(0)
C
13

I think you are misunderstanding the description given by MDN. Let me break it down.

The Window.requestAnimationFrame() method tells the browser that you wish to perform an animation

This means it will tell the browser that you wish to preform an animation that will require repainting. But to do that, we are going to need to run some code.

and requests that the browser call a specified function to update an animation before the next repaint.

This means that just before the next repaint, which the animation would require, call my callback function.

requestAnimationFrame is not a paint event callback, but a means of firing a callback before the next paint which the browsers must now preform.

Corriveau answered 21/2, 2015 at 18:52 Comment(1)
Thanks Alexander, your answer helps. I want to get other opinions too, so I will wait before I accept on final answer :)Dichromate
R
16

The following blog post really helped me understand how the whole thing works.

From it:

Essentially, the whole event loop function can be illustrated with this code:

while (eventLoop.waitForTask()) {  
    const taskQueue = eventLoop.selectTaskQueue()
    if (taskQueue.hasNextTask()) {
        taskQueue.processNextTask()
    }

    const microtaskQueue = eventLoop.microTaskQueue
    while (microtaskQueue.hasNextMicrotask()) {
        microtaskQueue.processNextMicrotask()
    }

    if (shouldRender()) {
        applyScrollResizeAndCSS()
        runAnimationFrames()
        render()
    }
}

And depict like so:

A diagram showing the task/microtask/and animationframe queue

Rooks answered 22/9, 2016 at 21:5 Comment(1)
Just reading this answer. Thanks for linking to that awesome post and your answer.Dichromate
C
13

I think you are misunderstanding the description given by MDN. Let me break it down.

The Window.requestAnimationFrame() method tells the browser that you wish to perform an animation

This means it will tell the browser that you wish to preform an animation that will require repainting. But to do that, we are going to need to run some code.

and requests that the browser call a specified function to update an animation before the next repaint.

This means that just before the next repaint, which the animation would require, call my callback function.

requestAnimationFrame is not a paint event callback, but a means of firing a callback before the next paint which the browsers must now preform.

Corriveau answered 21/2, 2015 at 18:52 Comment(1)
Thanks Alexander, your answer helps. I want to get other opinions too, so I will wait before I accept on final answer :)Dichromate

© 2022 - 2024 — McMap. All rights reserved.