tags:

views:

121

answers:

4

I'm using the module pattern, one of the things I want to do is dynamically include an external JavaScript file, execute the file, and then use the functions/variables in the file in the return { } of my module.

I can't figure out how to do this easily. Are there any standard ways of performing a pseudo synchronous external script load?

function myModule() {
    var tag = document.createElement("script");
    tag.type = "text/javascript";
    tag.src = "http://some/script.js";
    document.getElementsByTagName('head')[0].appendChild(tag);

    //something should go here to ensure file is loaded before return is executed

    return {
        external: externalVariable 
    }
}
A: 

check this page out of High Performance Javascript

basically you tell it which script to load and then you can give it a callback function to run once it's done. i use this in production and it's awesome.

Jason
A: 

You can't and shouldn't perform server operations synchronously for obvious reasons. What you can do, though, is to have an event handler telling you when the script is loaded:

tag.onreadystatechange = function() { if (this.readyState == 'complete' || this.readyState == 'loaded') this.onload({ target: this }); };

tag.onload = function(load) {/*init code here*/}

onreadystatechange delegation is, from memory, a workaround for IE, which has patchy support for onload.

Igor Zevaka
Saying 'You can't' is directly wrong as shown by my answer ;)
Sean Kinsey
I stand corrected.
Igor Zevaka
+1  A: 

There is only one way to synchronously load and execute a script resource, and that is using a synchronous XHR

This is an example of how to do this

// get some kind of XMLHttpRequest
var xhrObj = createXMLHTTPObject();
// open and send a synchronous request
xhrObj.open('GET', "script.js", false);
xhrObj.send('');
// add the returned content to a newly created script tag
var se = document.createElement('script');
se.type = "text/javascript";
se.text = xhrObj.responseText;
document.getElementsByTagName('head')[0].appendChild(se);

But you shouldn't in general use synchronous requests as this will block everything else. But that being said, there are of course scenarios where this is appropriate.

I would probably refactor the containing function into a asynchronous pattern though using an onload handler.

Sean Kinsey
I ended up refactoring so that onload/onreadystate change would work. But this is the correct answer to my original question.
spoon16
A: 

I use jquery load method applied to div element. something like

<div id="js">
<!-- script will be inserted here --> 
</div>

...

$("#js").load("path", function() {  alert("callback!" });

You can load scripts several times and each time one script will completely replace the one loaded earlier

Andrew Florko