添加脚本标签并按顺序加载脚本



>我有以下函数来加载给定的脚本:

function addScriptTag(url){
var script = document.createElement('script');
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
}

我使用该函数加载彼此相关的库,其中lib2依赖于lib1lib1取决于jquery

function loadThemAll(){
addScriptTag('http://path/to/jquery.js');
addScriptTag('http://path/to/lib1.js');
addScriptTag('http://path/to/lib2.js');
}

问题是,即使按照这个顺序,当lib1需要jQuery时,它也找不到它。这同样适用于使用lib1lib2

如何使脚本标签按顺序创建和加载脚本? 换句话说:

jQuery添加脚本标记并加载它。

加载jQuery后,添加lib1的脚本标记并加载它。

加载lib1后,添加lib2的脚本标记并加载它。

在尝试加载下一个脚本之前,您不会等待上一个脚本加载,您可以尝试使用Promises和脚本元素的onload回调。

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');
});

由于新脚本的onload方法设置为返回的PromiseaddScriptTag的解析,这应该会导致脚本等到加载前一个脚本。

您可以更进一步,编写一个函数,该函数需要按顺序加载脚本列表:

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");
});

addScriptTag返回一个在加载脚本时解析的 Promise,并await每次调用:

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);
});

您也可以使用async=false,但这会在脚本加载之前阻止,因此可能不是一个好主意:

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');
}

您可以将defer属性添加到脚本中。有关更多详细信息,请参阅此问题

最新更新