Does javascript process using an elastic racetrack algorithm

Flash’s “elastic racetrack” was inherited from the browser. Of course, in browser-land we don’t call it that – we call it the event loop.

The history of javascript’s event loop started out with progressive GIF and JPEG rendering on Netscape. Progressive rendering – the drawing of partially loaded content – required Netscape to implement an asynchronous download-render engine. When Brendan Eich implemented javascript this asynchronous event loop was already there. So it was a fairly simple task to add another layer to it.

The browser’s event loop is therefore something like the following:

    Event loop
        ┌──────────┐
        │          │
        │          │
        │          ▼
        │        check if there's any new ───────▶ parse data
        │        data on the network                    │
        │          │                                    │
        │          ▼                                    │
        │        check if we need to execute  ◀─────────┘
        │        any javascript ──────────────────▶ execute
        │          │                               javascript
        │          ▼                                  │
        │        check if we need to ◀────────────────┘
        │        redraw the page  ──────────────▶ redraw page
        │          │                                   │
        │          │                                   │
        └────◀─────┴─────────────────◀─────────────────┘

The rest, as they say, is history. When Microsoft copied javascript they had to duplicate the event loop to remain compatible with Netscape. So form then on everyone had to do the same to remain compatible with Netscape and IE.

Note that javascript doesn’t have any functionality to recurse into the event loop manually (some languages, like tcl for example, can do it) so the browser MUST wait until there is no more javascript to execute before redrawing the page. Page redraws cannot be forced to happen until the end of script.

It is for this reason that calculated values like an element’s width or height sometimes return the wrong value when you try to read them immediately after creation – the browser hasn’t drawn them yet. The work-around if you really need to execute code after page redraw is to use a setTimeout with a timeout value of 0 to allow the browser to run one round of the event loop.


Additional detail:

There appears to be one exceptional condition that triggers expensive reflows. Note that a reflow is the browser calculating page layout. It’s usually triggered if the browser needs to draw a changed page.

When something in the page changes, a reflow calculation is queued – not immediately executed. As in the description above, the reflow will only be executed at the end of the javascript execution. But there is one case that causes the browser to execute reflow calculations immediately: if you try to read any of the calculated values such as width and height.

See this related question for more info: When does reflow happen in a DOM environment?

Leave a Comment