views:

131

answers:

2

UPDATE:

I have the following code:

<script type="text/javascript">
function addScript(url) {
    var script = document.createElement('script');
    script.src = url;
    document.getElementsByTagName('head')[0].appendChild(script);
}   
addScript('http://google.com/google-maps.js');
addScript('http://jquery.com/jquery.js');

...

// run code below this point once both google-maps.js & jquery.js has been downloaded and excuted

</script>

How can I prevent code from executing until all required JS have been downloaded and executed? In my example above, those required files being google-maps.js and jquery.js.

+4  A: 

You can use the onload event of the script element for most browsers, and use a callback argument:

Edit: You can't really stop the execution of the code when you load scripts in this way (and making synchronous Ajax requests is a bad idea most of the times).

But you can chain callbacks, so if you have some code that depends on both, Two.js and Three.js, you can chain the loading actions, for example:

loadScript('http://example.com/Two.js', function () {
  // Two.js is already loaded here, get Three.js...
  loadScript('http://example.com/Three.js', function () {
    // Both, Two.js and Three.js loaded...
    // you can place dependent code here...
  });
});

Implementation:

function loadScript(url, callback) {
  var head = document.getElementsByTagName("head")[0],
      script = document.createElement("script"),
      done = false;

  script.src = url;

  // Attach event handlers for all browsers
  script.onload = script.onreadystatechange = function(){
    if ( !done && (!this.readyState || // IE stuff...
      this.readyState == "loaded" || this.readyState == "complete") ) {
      done = true;
      callback(); // execute callback function

      // Prevent memory leaks in IE
      script.onload = script.onreadystatechange = null;
      head.removeChild( script );
    }
  };
  head.appendChild(script);
}

For IE, the onreadystatechange event has to be bound.

CMS
I'm a bit confused, so should I use the code above or the code you linked too?
Henryh
@Henryh, Use the code I linked, it is cross-browser, and it will work without problems on IE, it even cares about some well known [memory leaks](http://ajaxian.com/archives/dynamic-script-generation-and-memory-leaks), I didn't wanted to *cross-post* it here...
CMS
okay, thanks CMS. would you mind then updating your code above to be the same as the code on the linked page. It will make it less confusing for future people to know which code to use. Thanks again.
Henryh
@CMS, I actually just realized my problem is a bit different than when i originally posted it. Please note that my actual question is that I need a script that let's me asynchronously download my JS but also not execute certain code until all required files have been downloaded. Any suggestions? Many thanks in advance.
Henryh
@CMS, any ideas based on my new question? You've been super helpful so far and hoping you understand my new question.
Henryh
@Henryh, give a look to my edit.
CMS
@CMS, thanks for the update. To give more info on my particular use case, I have 2 JS files I need to wait for download and execution before I can begin executing my code on HTML. 1) Google Maps, 2) JQuery. As such, before I can execute my code embedded within my HTML page, I need both Google Maps and JQuery to exist. I want to provide the fastest response time, so I thought using a DOM insert would be the way. Is this not correct? Would simply using a SCRIPT tag for each Google Maps and JQuery be the fastest way for me to load the two dependencies?
Henryh
@Henryh, of course, simply putting a `<script src="..."></script>` tag in your document will cause the DOM parsing to stop and wait to load and execute the script.
CMS
@CMS, but what I'm asking is ... given my use case, what would be the fastest way to load all of my JavaScript. Would that be simply using <script> or asynchronously but chaining the downloads like your example above?
Henryh
@CMS, I guess what I'm saying is... how is your code using chaining functionally different that using <script> since they would both delay loading the javascript until the previous loads and it's not asynchronous.
Henryh
Please note that google-maps.js doesn't need jquery.js, and jquery.js doesn't need google-maps.js ... BUT, the code after I download those two files do need BOTH already loaded.
Henryh
@Henryh, I would put all the script tags (jQuery, Google Maps and your code), [at the bottom](http://developer.yahoo.com/performance/rules.html#js_bottom) just before closing the `</body>`, that will let the browser to parse the complete DOM tree and then load your scripts sequentially.
CMS
A: 

I just read CMS's answer, and decided that from his "most browsers" comment, I might have a crack at getting it work for ones that do not have this functionality natively.

Basically, it's an interval that polls for a variable.

var poll = window.setInterval(function() {

    if (typeof myVar !== 'undefined') {
        clearInterval(poll);
        doSomething();
    };

}, 100);
alex
@alex Yes, by *"most browsers"* I usually refer to anything that is not IE :)
CMS
@CMS Not sure if my answer adds anything then. It's a bit hacky, especially if there are better alternatives.
alex
@alex well, personally I don't like timers to do this kind of stuff when you can use events, however it is a completely valid answer...
CMS