我需要动态地(在 TypeScript 和 JavaScript 中)加载 x 个脚本(假设本例中有 6 个)。
前 2 个脚本被后 4 个脚本使用。所以我必须确保在加载最后 4 个脚本之前加载脚本 1 和 2。
var scripts = [
{ "path": "f1.js", "isDependency": true },
{ "path": "f2.js", "isDependency": true },
{ "path": "f3.js", "isDependency": false },
{ "path": "f4.js", "isDependency": false },
{ "path": "f5.js", "isDependency": false },
{ "path": "f6.js", "isDependency": false }
];
我有一个加载脚本的异步函数,但我在设置异步/等待时遇到问题,或者无法 promise 等待前 2 个脚本加载,然后让其他脚本以任何顺序加载。
private async loadJsFileAsync(filePath: string) {
return new Promise((resolve, reject) => {
if (!document.getElementById(filePath)) {
var script = document.createElement('script');
script.onload = function () {
// mark with attribute so we know that it's loaded
script.attributes["data-loaded"] = "true";
resolve();
}
script.onerror = function (err) {
reject(err);
}
script.type = "text/javascript";
script.src = filePath
script.id = filePath;
document.getElementsByTagName('head')[0].appendChild(script);
} else {
// file processed, but check to see it actually loaded
var s1 = <HTMLScriptElement>document.getElementById(filePath);
var loadedAttribute = s1.attributes["data-loaded"] === "true";
if (loadedAttribute) {
resolve();
} else {
// add event listeners (in addition to the existing ones)
s1.addEventListener("load", function () {
resolve();
});
s1.addEventListener("error", function (err) {
reject(err);
});
}
}
});
}
目前我通过以下方式仅将异步函数与一个必需的脚本一起使用:
this.loadJsFileAsync("f1.js").then(value => {
// load other files
loadJsFile("f3.js");
loadJsFile("f4.js");
loadJsFile("f5.js");
loadJsFile("f6.js");
});
private loadJsFile(filePath: string) {
var script = document.createElement('script');
script.type = "text/javascript";
script.src = filePath + this.version();
script.id = filePath;
document.getElementsByTagName('head')[0].appendChild(script);
}
最佳答案
首先,为什么不使用 requirejs 或其他模块加载器?它们为您提供链接脚本的能力,以便首先加载依赖项。其次,我认为这就是您想要的:
这里肯定有改进和优化的空间,但它应该会给你想要的结果。
class Script {
constructor(path, dependencyOrder) {
this.path = path;
this.dependencyOrder = dependencyOrder;
}
}
class ScriptLoader {
constructor() {
this.scripts = [];
}
addScript(script) {
const exists = this.scripts.find( s => s.path.toLowerCase() === script.path.toLowerCase());
if (!exists) {
this.scripts.push(script);
}
}
async loadScripts() {
if (Array.isArray(this.scripts)) {
const orderedScripts = this.orderScriptsByDependency();
let scriptsLoaded = false;
let counter = 0;
while (!scriptsLoaded) {
const _script = orderedScripts[counter]
await this.loadScript(_script, _script.dependencyOrder > -1);
counter += 1;
scriptsLoaded = counter === orderedScripts.length;
}
}
}
async loadScript(script, waitToLoad) {
return new Promise( (resolve, reject) => {
const scriptTag = document.createElement('script');
scriptTag.src = script.path;
if (waitToLoad) {
scriptTag.async = true;
document.body.appendChild(scriptTag);
scriptTag.onload = () => { resolve(); }
} else {
document.body.appendChild(scriptTag);
resolve();
}
} );
}
orderScriptsByDependency() {
if (Array.isArray(this.scripts)) {
return this.scripts.sort( (a, b) => {
return a.dependencyOrder - b.dependencyOrder;
});
}
return null;
}
}
用法
class IndexView {
constructor() {
this.loader = new ScriptLoader();
this.init();
}
async init() {
this.loader.addScript(new Script('scripts/script0.js', 0));
this.loader.addScript(new Script('scripts/script1.js', 1));
this.loader.addScript(new Script('scripts/script2.js', 2));
await this.loader.loadScripts();
}
}
关于javascript - 如何按特定顺序动态加载多个脚本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55602445/