3

I'm using a graph visualization library in $(document).ready() and it seems to block UI. I was expecting $(document).ready() to execute in a separate thread.

Does any one know about the details? Maybe I should use setTimeout to run the code asynchronously?

Edit:

The term "asynchronous" and "separate thread" is misleading in JavaScript. I'm not an expert of JavaScript and I can't find more accurate term. Please see the answers for clarification.

Jay
  • 601
  • 6
  • 17
  • 1
    `$(document).ready()` is same as `DOMcontentLoaded`! – Rayon Oct 09 '15 at 02:05
  • @RayonDabre no, there are differences. `onload` will wait for all visible external resources (such as an inline image) to load, while ready executes when the DOM it self is fully loaded, behaves something like loading the script right before ends. – TwilightSun Oct 09 '15 at 02:07
  • @RayonDabre, Does `DOMcontentLoaded` execute in the main thread? – Jay Oct 09 '15 at 02:08
  • @Amadan well then, I see he just made an edit. – TwilightSun Oct 09 '15 at 02:08
  • @Jay, **JavaScript is usually considered to have a single thread of execution** I am unable to understand the term `separate thread` you are using ! – Rayon Oct 09 '15 at 02:10
  • _"using a graph visualization library in $(document).ready() and it seems to block UI"_ Not certain interpret "seems to block UI" correctly ? Can create stacksnippets to demonstrate ? What is expected result ? – guest271314 Oct 09 '15 at 02:19
  • JavaScript runs on a single thread. Asynchronous code executes on the main thread but doesn't block the main thread. When a function runs async that means it doesn't stop subsequent function calls. See http://stackoverflow.com/questions/11043656/async-and-document-ready for additional details. –  Oct 09 '15 at 02:20

3 Answers3

5

With the exception of Web Workers (which do not have direct access to DOM), JavaScript runs in a single thread. $(document).ready() is asynchronous in the sense that the callback you pass to it may fire right away or sometime later when the DOM is loaded, but when its callback actually runs, it is the only thing that the JS runtime is processing.

A long-running for loop, for instance, will block the UI thread regardless of whether it is in a ready callback, an event handler, an async XHR's success callback, etc. The only way to prevent it from blocking the thread would be to break it up into several loops by scheduling later chunks using setTimeout.

Ken Franqueiro
  • 10,559
  • 2
  • 23
  • 40
2

There is no separate thread in JavaScript. All JavaScript is executing in a single thread; UI updates are executing in the same thread. If your JavaScript is busy, UI updates do not happen. "asynchronous" is a bit of a misleading term here; it means that execution of a function will be deferred (but still in a single thread).

Basically, a browser has an execution queue. All event handlers are put into the execution queue when they are triggered; as are timeout functions. When any function with no callers exits, the next function in the queue is executed. UI updates are also in the same queue.

So when you do $(document).ready(fn), it (in simple terms; jQuery makes it a bit complex, especially for older browsers) will attach a handler. This handler will get triggered by the browser when all the content is loaded, which will put it onto the execution queue. When it is its turn, it will execute; any UI updates it performs will be painted when the handler exits.

--

*) There is an exception to the single-thread rule: web workers. Each web worker runs in its own thread, but they are very limited as to what they can do; basically, computation only (they can't access UI at all).

Amadan
  • 191,408
  • 23
  • 240
  • 301
2

Asynchronous doesn't mean multithread. Javascript is event based, functions will be called when something happens (an event occurs). The event listening function is not executed on a separate thread, its just planned to be executed later.

But there one old technique to emulate multithread without the browser support for Web Workers. It's splitting up one whole task into deferring small tasks.

For example, you write this which will cause blocking:

for (var i = 0; i < 10000000; i++) {
    // do something very slow
}

Turn it to this, and it will execute parallel, almost like multithreaded.

(function step(i) {
    if (i < 10000000) {
        // do something very slow
        setTimeout(function() {step(i + 1)}, 1);
    }
})(0);

Edit: I just realized that this will cause memory problem, because in each step closure we are referencing the previous step, making it impossible for the GC to clean up memory. To overcome this, put i out of the arguments, and change it like this (I'm wrapping the whole thing with a function, so that i can not be changed mistakenly outside):

(function() {
    var i = 0;
    (function step() {
        if (i < 10000000) {
            // do something very slow
            i++;
            setTimeout(step, 1);
        }
    })();
})();
TwilightSun
  • 2,275
  • 2
  • 18
  • 27