Which queue is associated with requestAnimationFrame?

441 Views Asked by At

Today I was asked this question on an interview. I couldn't answer this question and the interviewer said there was a special queue for requestAnimationFrame callbacks. But I can't find any information on this.

If rAF has it's own queue then why is this queue never mentioned anywhere? We only mention macro- and microtask queues when we talk about Event Loop?

3

There are 3 best solutions below

18
Kaiido On BEST ANSWER

We only mention macro- and microtask queues when we talk about Event Loop?

First, there is no mention of "macro" task in the specs, only tasks and microtasks (and then callbacks, more on that later).

Then, almost every task source have their own task queues in modern browsers, though they currently don't have to. So there isn't just two queues, one that would be the microtask queue and another one for all the tasks, there are a lot of task queues (each MessagePort instance can have its own task queue). This allows to have various priority for each task source. So that UI events can get treated before network ones, for instance.

But requestAnimationFrame callbacks are not even queued in a task queue. This method schedules a callback that (in the specs1) isn't invoked from a task, but from a special place in the event loop called "update the rendering", itself visited only once in a while (generally when the monitor sends a VSync signal and the document is active), which will also fire scroll and resize events, Web Animation updates, ResizeObserver callbacks, etc. and the rendering of the page.

This is important that conceptually all these steps are not executed in a tasks, because this means that any task queued from these callbacks will not get executed before the next rendering, while still ensuring that a ResizeObserver callback scheduled from a resize event for instance, will be called before.

Animation frame callbacks are stored in an ordered map, called the map of animation frame callbacks. It's not a queue per-se, since we can "cancel" the callbacks through the cancelAnimationFrame() method. Also this allows getting all the keys at the beginning of the run the animation frame callbacks algorithm which itself allows to schedule new callbacks from such a callback to the next animation frame without blocking the event loop forever (if it were a queue, the algorithm would keep calling new callbacks endlessly, like it does in the microtask checkpoint).

But that much details is a bit pedantic and unless you're really into this kind of stuff you shouldn't need to know more than

  • most native events and Web API callbacks are queued in task queues, which get visited at the beginning of the event loop with a prioritization system,
  • all microtasks are executed every time after a callback has been invoked, in a way you can stuck the event loop if queuing microtasks from a microtask,
  • some render-related native events and animation frames are treated in their own place in the event loop.

Still, I believe it's good to understand that there is this special update the rendering step in the event loop, that is distinct from the other queued tasks in that it doesn't participate in the task prioritization system. I often read that it has an higher priority but IMO it's wrong to say that and given we'll soon have true control over some tasks prioritization, it will grow more important. It also helps understand when the styles recalc are performed and the relationship with (synchronous) DOM updates, and other stuff related to the rendering in a browser. But if you're not applying to a position that involves the details of browser rendering, maybe they just expected the (IMO pretty bad and) colloquial "in the render queue", as is being used e.g. in P.Roberts's Loupe.

1: Firefox, for one, actually queues tasks even for these, but they do it in a way it's not observable.

6
trincot On

requestAnimationFrame is specific to the Web API. The callback that is given as argument is collected in an ordered map, which the HTML Standard identifies as a map of animation frame callbacks. This map is associated with the HTML document (or the global scope in case of a dedicated web worker).

This map (which can be understood as a queue), gets processed after the current task has completed, including the processing of the microtask queue. This map is consumed as part of the rendering phase of the event loop. The HTML Standard specifies as step 13 of the rendering process:

  1. For each fully active Document in docs, run the animation frame callbacks for that Document, passing in now as the timestamp.

So the short answer to "which queue" would be: the map of animation frame callbacks as specified in the HTML Standard.

4
Daniel Beck On

requestAnimationFrame has its own queue separate from DOM events. The events are invoked during the rendering phase of the event loop.

The spec calls it the "animation frame request callback list" -- though I wouldn't expect anyone other than a browser developer to be able to recite that name in an interview situation! For most web developers, this is browser-internal detail that doesn't normally impact the day to day; I'm surprised this was used as an interview question (unless you're interviewing to work for a browser developer.)

Here's a duplicate (but unanswered) question which has some more links in comments you might find useful.