64

Here's my issue - I need to dynamically download several scripts using jQuery.getScript() and execute certain JavaScript code after all the scripts were loaded, so my plan was to do something like this:

function GetScripts(scripts, callback)
{
  var len = scripts.length
  for (var i in scripts)
  {
    jQuery.getScript(scripts[i], function() 
    {
      len --;
      // executing callback function if this is the last script that loaded
      if (len == 0)
        callback()  
    })
  }
}

This will only work reliably if we assume that script.onload events for each script fire and execute sequentially and synchronously, so there would never be a situation when two or more of the event handlers would pass check for (len == 0) and execute callback method.

So my question - is that assumption correct and if not, what's the way to achieve what I am trying to do?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andrey
  • 20,487
  • 26
  • 108
  • 176
  • 1
    javascript is multithreaded, heres a link to check out to show an example: http://ajaxian.com/archives/multi-threaded-javascript – Anthony Forloney Nov 02 '09 at 19:23
  • 6
    @aforloney - that's not exactly right. As the Sun engineer cited in the article says, the **Rhino JavaScript engine** "allows Java method calls. So, we can use that to create script wrappers for Java platform classes… we can easily create threads in script." – Jeff Sternal Nov 02 '09 at 20:22
  • [async.js](https://github.com/caolan/async) is great for executing code after all script, run either parallel or in sequence, are completed – Maxim Krizhanovsky Jul 07 '13 at 07:37

9 Answers9

88

No, JavaScript is not multi-threaded. It is event driven and your assumption of the events firing sequentially (assuming they load sequentially) is what you will see. Your current implementation appears correct. I believe jQuery's .getScript() injects a new <script> tag, which should also force them to load in the correct order.

gnarf
  • 105,192
  • 25
  • 127
  • 161
  • I basically don't care whether about the order of loading, I just need to make sure that my callback function will only get executed when all of the scripts are loaded, because it depends on all of them. – Andrey Nov 02 '09 at 19:27
  • 9
    This is probably an embarrassing simple-minded question, but if JavaScript is not multi-threaded, why do multiple chained jQuery animations (for example) appear to happen simultaneously instead of in sequence? – Larry Lustig Nov 02 '09 at 19:32
  • 12
    The animation updates are triggered by timer events being fired. – Jacob Nov 02 '09 at 19:37
  • 12
    As far as I understand, animations are using timers, and each animation is not a single process but a sequence of small incremental changes on some timer event, hence it seems like multiple animations happen simultaneously – Andrey Nov 02 '09 at 19:37
36

Currently JavaScript is not multithreaded, but the things will change in near future. There is a new thing in HTML5 called Worker. It allows you to do some job in background.

But it's currently is not supported by all browsers.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ivan Nevostruev
  • 28,143
  • 8
  • 66
  • 82
  • Worker is a new thing in Javascript implementation, but I don't see how it has anything to do with HTML 5 – Andrey Nov 02 '09 at 19:39
  • Oh... yes, my bad... don't know where I get it from – Ivan Nevostruev Nov 02 '09 at 19:47
  • 5
    Web Workers is part of the HTML5 specification. http://www.whatwg.org/specs/web-workers/current-work/ – Rob Nov 02 '09 at 19:52
  • Just came accross. I have one post : http://www.helloworldgeeks.com/blogs/abhishek/standard-blog/8/multithreading-in-javascript-webworkers-html5 – abhishek Sep 30 '12 at 15:34
  • 8
    Two things to note about Workers is that they do not have access to the DOM and cannot access the parent page. – Seanny123 Sep 10 '13 at 06:30
  • 1
    Now workers are supported in all new browsers (IE 10 was the last to get on board) http://www.w3schools.com/html/html5_webworkers.asp – CodeMonkey Nov 21 '16 at 17:47
  • Is this original post outdated? There haven't been any updates in years. I'm wondering, *if JavaScript is not multithreaded how do things like async calls, event listeners, Promises, and etc work?* What is managing these asynchronous/parallel events? Is it more appropriate to think of individual JS call stacks as single threaded, but a multitude of async JS actions in the browser as a collection of "threads" controlled by the DOM? – h0r53 Apr 26 '21 at 22:59
  • Furthermore, if I hit a breakpoint in my browser developer console, why do things like Intervals still execute? Is a context switch occurring? What controls it? – h0r53 Apr 26 '21 at 23:07
  • @h0r53 setinterval, fetch, settimeout, promises etc they are browser APIs which are handled by browser itself. – norbekoff May 27 '22 at 13:12
18

The JavaScript (ECMAScript) specification does not define any threading or synchronization mechanisms.

Moreover, the JavaScript engines in our browsers are deliberately single-threaded, in part because allowing more than one UI thread to operate concurrently would open an enormous can of worms. So your assumption and implementation are correct.

As a sidenote, another commenter alluded to the fact that any JavaScriptengine vendor could add threading and synchronization features, or a vendor could enable users to implement those features themselves, as described in this article: Multi-threaded JavaScript?

Community
  • 1
  • 1
Jeff Sternal
  • 47,787
  • 8
  • 93
  • 120
14

JavaScript is absolutely not multithreaded - you have a guarantee that any handler you use will not be interrupted by another event. Any other events, like mouse clicks, XMLHttpRequest returns, and timers will queue up while your code is executing, and run one after another.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dan Monego
  • 9,637
  • 6
  • 37
  • 72
11

No, all the browsers give you only one thread for JavaScript.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hannoun Yassir
  • 20,583
  • 23
  • 77
  • 112
7

To be clear, the browser JS implementation is not multithreaded.

The language, JS, can be multi-threaded.

The question does not apply here however.

What applies is that getScript() is asynchronous (returns immediately and get's queued), however, the browser will execute DOM attached <script> content sequentially so your dependent JS code will see them loaded sequentially. This is a browser feature and not dependent on the JS threading or the getScript() call.

If getScript() retrieved scripts with xmlHTTPRequest, setTimeout(), websockets or any other async call then your scripts would not be guaranteed to execute in order. However, your callback would still get called after all scripts execute since the execution context of your 'len' variable is in a closure which persists it's context through asynchronous invocations of your function.

bucabay
  • 5,235
  • 2
  • 26
  • 37
4

JS in general is single threaded. However HTML5 Web workers introduce multi-threading. Read more at http://www.html5rocks.com/en/tutorials/workers/basics/

balaji ap
  • 66
  • 2
1

Thought it might be interesting to try this out with a "forced", delayed script delivery ...

  1. added two available scripts from google
  2. added delayjs.php as the 2nd array element. delayjs.php sleeps for 5 seconds before delivering an empty js object.
  3. added a callback that "verifies" the existence of the expected objects from the script files.
  4. added a few js commands that are executed on the line after the GetScripts() call, to "test" sequential js commands.

The result with the script load is as expected; the callback is triggered only after the last script has loaded. What surprised me was that the js commands that followed the GetScripts() call triggered without the need to wait for the last script to load. I was under the impression that no js commands would be executed while the browser was waiting on a js script to load ...

var scripts = [];
scripts.push('http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js');
scripts.push('http://localhost/delayjs.php');
scripts.push('http://ajax.googleapis.com/ajax/libs/scriptaculous/1.8.3/scriptaculous.js');


function logem() {
    console.log(typeof Prototype);
    console.log(typeof Scriptaculous);
    console.log(typeof delayedjs);
}

GetScripts( scripts, logem );

console.log('Try to do something before GetScripts finishes.\n');
$('#testdiv').text('test content');

<?php

sleep(5);
echo 'var delayedjs = {};';
dan_nl
  • 4,456
  • 1
  • 15
  • 7
  • 2
    Well, don't confuse yourself - browser downloads scripts outside of javascript thread, hence javascript proceeds without waiting for scripts to load – Andrey Nov 02 '09 at 22:09
0

You can probably get some kind of multithreadedness if you create a number of frames in an HTML document, and run a script in each of them, each calling a function in the main frame that should make sense of the results of those functions.

Ibolit
  • 9,218
  • 7
  • 52
  • 96