NOT A DUPLICATE AS I HAVE YET TO FOUND A SATISFYING ANSWER ON OTHER THREADS:
- Load and execute javascript code SYNCHRONOUSLY
- Loading HTML and Script order execution
- Load and execute javascript code SYNCHRONOUSLY
Looking for native Javascript answers, no jQuery, no requireJS, and so forth please :)
SUMMARY OF THE ENTIRE QUESTION:
I want to asynchronously load scripts but have ordered execution
I am trying to enforce that the code in the inserted script elements execute exactly in the same order as they were added to the dom tree.
That is, if I insert two script tags, first and second, any code in first must fire before the second, no matter who finishes loading first.
I have tried with the async attribute and defer attribute when inserting into the head but doesn't seem to obey.
I have tried with element.setAttribute("defer", "") and element.setAttribute("async", false) and other combinations.
The issue I am experiencing currently has to do when including an external script, but that is also the only test I have performed where there is latency.
The second script, which is a local one is always fired before the first one, even though it is inserted afterwards in the dom tree ( head ).
A) Note that I am still trying to insert both script elements into the DOM. Ofcourse the above could be achieved by inserting first, let it finish and insert the second one, but I was hoping there would be another way because this might be slow.
My understanding is that RequireJS seems to be doing just this, so it should be possible. However, requireJS might be pulling it off by doing it as described in A).
Code if you would like to try directly in firebug, just copy and paste:
function loadScript(path, callback, errorCallback, options) {
var element = document.createElement('script');
element.setAttribute("type", 'text/javascript');
element.setAttribute("src", path);
return loadElement(element, callback, errorCallback, options);
}
function loadElement(element, callback, errorCallback, options) {
element.setAttribute("defer", "");
// element.setAttribute("async", "false");
element.loaded = false;
if (element.readyState){ // IE
element.onreadystatechange = function(){
if (element.readyState == "loaded" || element.readyState == "complete"){
element.onreadystatechange = null;
loadElementOnLoad(element, callback);
}
};
} else { // Others
element.onload = function() {
loadElementOnLoad(element, callback);
};
}
element.onerror = function() {
errorCallback && errorCallback(element);
};
(document.head || document.getElementsByTagName('head')[0] || document.body).appendChild(element);
return element;
}
function loadElementOnLoad(element, callback) {
if (element.loaded != true) {
element.loaded = true;
if ( callback ) callback(element);
}
}
loadScript("http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js",function() {
alert(1);
})
loadScript("http://ajax.googleapis.com/ajax/libs/chrome-frame/1.0.3/CFInstall.min.js",function() {
alert(2);
})
If you try the above code in like firebug, most often it will fire 2, and then 1. I want to ensure 1 and then 2 but include both in the head.