If you embed several script tags in your head like this, using a mixture of local and remote script files, you may experience a situation where local scripts that depend on external scripts (for example, loading jQuery from googleapis) will fail because external scripts may not Loads earlier than local ones.
So something like this will have a problem: ("jQuery is not defined" in jquery.some-plugin.js).
var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; script.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"; head.appendChild(script); var script = document.createElement('script'); script.type = 'text/javascript'; script.src = "/jquery.some-plugin.js"; head.appendChild(script);
Of course, in this situation .onload () is used, but if multiple scripts are loaded, this can be cumbersome.
As a solution to this situation, I put together this function, which will store the script queue for loading, loading each subsequent element after the previous one is completed, and returns a promise that is resolved when the script (or the last script in the queue, if without parameters) is loaded.
load_script = function(src) { // Initialize scripts queue if( load_script.scripts === undefined ) { load_script.scripts = []; load_script.index = -1; load_script.loading = false; load_script.next = function() { if( load_script.loading ) return; // Load the next queue item load_script.loading = true; var item = load_script.scripts[++load_script.index]; var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; script.src = item.src; // When complete, start next item in queue and resolve this item promise script.onload = () => { load_script.loading = false; if( load_script.index < load_script.scripts.length - 1 ) load_script.next(); item.resolve(); }; head.appendChild(script); }; }; // Adding a script to the queue if( src ) { // Check if already added for(var i=0; i < load_script.scripts.length; i++) { if( load_script.scripts[i].src == src ) return load_script.scripts[i].promise; } // Add to the queue var item = { src: src }; item.promise = new Promise(resolve => {item.resolve = resolve;}); load_script.scripts.push(item); load_script.next(); } // Return the promise of the last queue item return load_script.scripts[ load_script.scripts.length - 1 ].promise; };
With this addition of scripts, to make sure that the previous is done, before proceeding to the next, you can do as ...
["https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js", "/jquery.some-plugin.js", "/dependant-on-plugin.js", ].forEach(load_script);
Or download the script and use the Promise return to do the work after it's finished ...
load_script("some-script.js") .then(function() { });