I have the following function that loads a given script :
function addScriptTag(url){
var script = document.createElement('script');
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
}
I used the function to load libs correlated to each other where lib2
depends on lib1
and lib1
depends on jquery
:
function loadThemAll(){
addScriptTag('http://path/to/jquery.js');
addScriptTag('http://path/to/lib1.js');
addScriptTag('http://path/to/lib2.js');
}
The problem is that even in that order, when lib1
needs jQuery, it doesn't find it. The same applies for lib2
that uses lib1
.
How can I make script tag creates and load the script sequentially ? In other words :
add script tag for jQuery
and load it.
When jQuery
is loaded, add script tag for lib1
and load it.
When lib1
is loaded, add script tag for lib2
and load it.
You aren't waiting for the previous script to load before attempting to load the next one, you could try using Promises
and the onload
callback of the script elements.
function addScriptTag(url) {
return new Promise(function (resolve, reject) {
var script = document.createElement('script');
script.onload = resolve;
script.onerror = reject;
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
})
}
addScriptTag('http://path/to/jquery.js').then(function() {
return addScriptTag('http://path/to/lib1.js');
}).then(function() {
return addScriptTag('http://path/to/lib2.js');
});
Since the onload
method of the new script is set to the resolve of the returned Promise
of addScriptTag
this should cause the scripts to wait until the previous one was loaded.
You could take it a step further and write a function that takes a list of scripts to load sequentially:
function loadScripts(scripts, promise) {
if (!promise) {
promise = new Promise();
}
script = scripts.shift();
if (script) {
addScriptTag(script).then(function () {
loadScripts(scripts, promise);
}).catch(function () {
promise.reject();
});
} else {
promise.resolve();
}
return promise;
}
loadScripts([
'http://path/to/jquery.js',
'http://path/to/lib1.js',
'http://path/to/lib2.js'
]).then(function () {
console.log("Scripts loaded");
});
Have addScriptTag
return a Promise that resolves when the script is loaded, and await
each call:
function addScriptTag(url){
return new Promise((resolve, reject) => {
var script = document.createElement('script');
script.addEventListener('load', resolve);
script.addEventListener('error', reject);
script.src = url;
document.head.appendChild(script);
});
}
async function loadThemAll(){
await addScriptTag('http://path/to/jquery.js');
await addScriptTag('http://path/to/lib1.js');
await addScriptTag('http://path/to/lib2.js');
}
loadThemAll()
.then(() => {
console.log('Everything is loaded!');
})
.catch((err) => {
console.log('There was a problem:', err);
});
You can also use async=false
, but this will block until the script loads, so may not be a great idea:
function addScriptTag(url){
var script = document.createElement('script');
script.setAttribute('async', 'false');
script.src = url;
document.head.appendChild(script);
}
function loadThemAll(){
addScriptTag('http://path/to/jquery.js');
addScriptTag('http://path/to/lib1.js');
addScriptTag('http://path/to/lib2.js');
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With