0

Event loop in the browser generally includes these steps, repeatedly:

  1. executing script (task)
  2. executing microtasks
  3. render updates (if the browser is ready to present the next frame)

Meanwhile in our code, reading properties like el.offsetHeight (full list here) could cause the browser to recalculate styles and perform layout synchronously, in order to return the up-to-date value. Does this change the event loop? For example, given this script block:

el.style.width = "200px"; // invalidate the style
el.offsetHeight; // forced synchronous layout
foo();
console.log("script end");

Usually, the whole block would be a task, the browser executes it to the last line, processes all the microtasks, then render updates if necessary. But with the second line triggering synchronous layout, how would the event loop be like? Does it pause executing, jump to step 3), render the updates, and continue with the rest of the code in the next tick, or does it just perform a layout and still be in step 1)?

Nayana Chandran
  • 1,416
  • 1
  • 16
  • 30
quanyc
  • 1
  • 3
  • "*Event loop in the browser generally includes these steps*" - no. Rendering is not part of the event loop. Layouting and rendering are generally a separate process from script execution. Sure, they're synchronised and sometimes should/need to wait for each other, but they are not strictly sequential and can benefit from parallelisation. – Bergi Jun 10 '21 at 09:01
  • @Bergi yes it is: https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering And layout has to be fetched synchonously when requested by scripts see https://stackoverflow.com/questions/47342730/javascript-are-dom-redraw-methods-synchronous/47343090#47343090 – Kaiido Jun 10 '21 at 09:02
  • @Kaiido Interesting. Still, the spec basically allows the browser to skip these steps at will, and/or run them later. I read this as a recommendation "after each event loop iteration, there's a good opportunity for layouting and rendering", but the actual implementation will be wildly different. And yes, sometimes a synchronous reflow is necessary, which is when the script execution needs to wait for the layouting thread, but in general these are independent. – Bergi Jun 10 '21 at 09:13
  • They don't really say it's optional no, this step is specced like that to allow the rendering to happen only when the monitor sends a v-sync signal, so that the rendering is throttled to the monitor refresh rate. It is mandatory that these steps execute at least a few times per seconds in active documents. (It's basically a lot of events that have been coalesced wirh requestAnimationFrame callbacks, when this latter has been specced.) – Kaiido Jun 10 '21 at 09:51

1 Answers1

1

The layout is not defined in the event-loop processing model1, so forcing such a layout doesn't have any influence on it.

What happens is that most browsers will wait before they actually need these updated values before calculating it, so this means that if nothing did request it, they'll wait until the "update the rendering" steps of the event-loop is called, which may be a few event-loop iterations later, and many microtask checkpoints later.

By calling it, you are just precipitating that event, and if you don't dirty the layout afterward, no bad would have been caused.

However, if you (or any script) do dirty the layout after forcing that reflow, a new reflow will take place before the rendering, meaning the browser will have had to calculate several times the boxes instead of just once, possibly slowing down your page, moreover on complicated pages.

1. The ResizeObserver API defined by W3C does include it in their specs, but they don't define the HTML's event loop processing, and their definition doesn't handle the case discussed here of forcing that reflow.

Kaiido
  • 123,334
  • 13
  • 219
  • 285