Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which code will run on the browser's main thread?

Chrome was the last of the big trio (IE, Firefox, Chrome) to deprecate running synchronous XMLHttpRequest calls on the "main thread" (as Firefox calls it). Some browsers have also completely removed the ability of setting the .widthCredentials option for synchronous requests on the main thread.

After searching far and wide, I couldn't find enough information to precisely identify which code will run on the main thread, and which will not.

It is obvious that javascript included via script tag (inline or with src) is on the main thread. And a synchronous XHR which runs inside the callback of an asynchronous XHR would not be running on the main thread.

But how about other scenarios? Mouse events, touch events, various document events? How to tell without trying everything? It would be nice to avoid making everything asynchronous and a callback hell.

Please attempt a thorough answer.

Edit: W3C spec warning: Developers must not pass false for the async argument when the JavaScript global environment is a document environment as it has detrimental effects to the end user's experience. User agents are strongly encouraged to warn about such usage in developer tools and may experiment with throwing an "InvalidAccessError" exception when it occurs so the feature can eventually be removed from the platform.

Edit 2: Clarification:

There are situations where calling code must either wait for all racing simultaneous async calls to finish (using some counters or state tracking variabiles for each call), or have them chained using callbacks. Each situation sucks. For example, I have a JSONRPC client which needs to dynamically create callable functions by interrogating a reflection API.

It is over the hand to have all implementing code (UI, or NOT) run inside the callback of yet another a library, especially if it has to be done on multiple pages, and if the library has to behave as a simple definition (hide that is running code at define time). This is just an example of complexity, I am not asking for a solution to it, but a general clear explanation of how browsers decide which is the main thread.

like image 564
Tiberiu-Ionuț Stan Avatar asked Sep 09 '14 23:09

Tiberiu-Ionuț Stan


2 Answers

As you have cited the W3C spec, it's easy to explain what you are hunting after:

Developers must not pass false for the async argument when the JavaScript global environment is a document environment as it has detrimental effects to the end user's experience.

What they mean document environment is explained in the processing models:

This specification describes three kinds of JavaScript global environments: the document environment, the dedicated worker environment, and the shared worker environment. The dedicated worker environment and the shared worker environment are both types of worker environments.

Except where otherwise specified, a JavaScript global environment is a document environment.

A "document environment" is therefore the global JavaScript environment of a page, i.e. the window that you see. Every JS global environment is single-threaded. Everything (really everything, you considered: Mouse events, touch events, various document events) runs in this environment. This is probably what Gecko considers a "main thread".

It would be nice to avoid making everything asynchronous and a callback hell

Making something asynchronous doesn't shift work from the main thread. It just defers it, making it possible for other events to run while you are waiting. If there is an asynchronous api for what you want to do (i.e. does processing in the background), use it. Make everything asynchronous.

There are enough techniques (e.g. promises!) to avoid a callback hell, which is just a sign of bad code.

Shifting work off the "main thread" requires you to create a new environment - a web worker. In that, you can do as many synchronous XMLHttpRequests as you want without being disturbed.

like image 51
Bergi Avatar answered Sep 29 '22 22:09

Bergi


Each browser is free to implement its own threading model as it sees fit. Different implementations will handle threading differently.

It is safe to say that if you are to block execution with JavaScript that you are doing something you shouldn't be. Even if you don't hang up the UI, browsers these days will prompt the user to abort your script. If you stay within a reasonable amount of blocking processing in your script, this isn't an issue. Synchronous XHR is something you should never do, as it isn't necessary and the time for which the thread will block is unpredictable.

like image 32
Brad Avatar answered Sep 29 '22 21:09

Brad