When you have code like this:
var scriptNode = document.createElement('script');
scriptNode.type = 'text/javascript';
scriptNode.charset = 'utf-8';
scriptNode.onload = function() {
console.log("Finished Loading Script");
//do stuff here
}
scriptNode.async = false;
scriptNode.src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js";
document.getElementsByTagName('body')[0].appendChild(scriptNode);
it is not actually true that the external script has executed and therefore stuff is ready to do at the onload point. Am I right in saying that onload does not mean "after the browser has processed and executed the JS and the external JS objects are ready to use"?
If this is true, is there a way to check that the browser has executed the script? I've tried using document.currentScript and that does not seem to deal with the execution delay.
Note that the jquery is just an example, I know that I can check for jquery using window.jQuery
or typeof
The situation I'm interested in is where you don't know what objects may be available after execution, where you're blind to the contents of the external script.
One approach I have been looking into is using Promises. In the following code, I set up a promise (the content of which does not really matter) and then get the promise to report.
function findScriptNode(source) {
return new Promise(function(resolve) {
var scripts = document.getElementsByTagName("script");
for (var i=0;i<scripts.length;i++) {
if (scripts[i].src && scripts[i].src === source) {
var timestamp = Date.now();
var finetimestamp = performance.now();
console.log(source + " Promise Event Timestamp: " + timestamp + " Performance Timestamp: " + finetimestamp);
resolve();
break;
}
}
});
}
var source = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js";
var scriptNode = document.createElement('script');
scriptNode.type = 'text/javascript';
scriptNode.charset = 'utf-8';
scriptNode.onload = function() {
var timestamp = Date.now();
var finetimestamp = performance.now();
console.log(source + " Load Event Timestamp: " + timestamp + " Performance Timestamp: " + finetimestamp);
findScriptNode(source).then(success => {
timestamp = Date.now();
finetimestamp = performance.now();
console.log(source + " Promise Complete Event Timestamp: " + timestamp + " Performance Timestamp: " + finetimestamp);
});
}
scriptNode.async = false;
scriptNode.src = source
document.getElementsByTagName('body')[0].appendChild(scriptNode);
With my limited understanding of the internals of Chrome JS execution, my understanding is that the following will happen in this order
- Script Tag created
- External Script Loaded
- Promise created and control handed back to the browser
- Browser will then continue executing the downloaded external script
- Once that execution has finished, the promise will resolve
It would have the advantage of waiting for the external script to execute (which may itself call loads of other scripts). Does that make any sense to anyone?
Any answers gratefully received.