我需要动态加载x脚本(假设本例为6)(在TypeScript和JavaScript中)。
前两个脚本由最后4个脚本使用,所以我必须确保脚本1和脚本2在加载最后4个脚本之前已经加载。
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 }
];而且我有一个加载脚本的异步函数,但是我在设置异步/等待或承诺等待前两个脚本加载,然后让其他脚本按任何顺序加载时遇到了问题。
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);
} 发布于 2019-04-09 23:38:39
首先,为什么不使用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();
}
}发布于 2019-04-10 00:14:07
如果你想保持秩序,你可以像这样利用onload of HtmlScriptElement。
const loadScripts = (urls: string[]): void => {
urls.forEach((url, index) => {
const js = loadScript(url);
if (index < urls.length) {
js.onload = () => {
loadScript(urls[index + 1]);
};
}
});
};
const loadScript = (url: string): HTMLScriptElement => {
const js = document.createElement("script");
js.setAttribute("src", url);
document.body.appendChild(js);
return js;
};就这样叫它:
loadScripts(["script1.js", "script2.js", "script3.js"]);https://stackoverflow.com/questions/55602445
复制相似问题