gpt4 book ai didi

javascript - 动态添加的脚本标签的加载顺序

转载 作者:太空狗 更新时间:2023-10-29 13:12:18 24 4
gpt4 key购买 nike

我有一个 typescript 应用程序,它动态添加指向 JS 文件的脚本标签。由于一些限制,我不能在 html 文件中静态定义这些脚本标签,所以我通过 typescript 动态添加它们,如下所示:

for (let src of jsFiles) {
let sTag = document.createElement('script');
sTag.type = 'text/javascript';
sTag.src = src;
sTag.defer = true;
document.body.appendChild(script);
}

现在,我注意到,当我动态添加脚本标签时,它们似乎不能保证它们的加载顺序。不幸的是,jsFiles 数组具有相互依赖的脚本。因此,数组中的第二个脚本只能在第一个完全加载后才能加载。第二个脚本引用第一个脚本中定义的函数。有没有一种方法可以指定动态添加脚本时脚本的排序和执行顺序(类似于在 html 文件中静态定义脚本标签时的排序方式)?

附言我想避免使用 onload 回调来解决这个问题,因为我注意到我的应用程序性能下降。我的第二个脚本文件非常大,我假设它导致了性能下降。

最佳答案

我可以提及一些替代方案来克服该要求:

  1. 使用库注入(inject)依赖项(AMD 或 CommonJS 模块)
    只需使用modules 。 ES2015:import/export,或 CommonJS:require()
  2. 以编程方式创建 script 标记并设置回调 onload 以便在异步加载脚本时使用react。默认设置属性 async = true
  3. 如果您被允许修改要注入(inject)的脚本,则在脚本末尾添加一行带有objectarray 的跟踪脚本已经加载。
  4. 您可以将脚本作为文本 (XMLHttpRequest) 获取,然后按要求的顺序使用脚本构建一个 string,最后通过以下方式执行文本脚本eval()
  5. 还有一个不太推荐但经常使用的选项,设置一个 setInterval 来检查脚本是否已经执行。

我建议选择第一个选项。但出于学术目的,我将说明第二种选择:

Create the script tag programmatically and set the callback onload in order to react when the script has been loaded asynchronously.

我想推荐一本关于脚本加载器的读物: Deep dive into the murky waters of script loading ,值得花半个小时!

下面的例子是一个管理脚本注入(inject)的小模块,这是它背后的基本思想:

let _scriptsToLoad = [
'path/to/script1.js',
'path/to/script2.js',
'path/to/script3.js'
];

function createScriptElement() {
// gets the first script in the list
let script = _scriptsToLoad.shift();
// all scripts were loaded
if (!script) return;
let js = document.createElement('script');
js.type = 'text/javascript';
js.src = script;
js.onload = onScriptLoaded;
let s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(js, s);
}

function onScriptLoaded(event) {
// loads the next script
createScriptElement();
};

在此plunker中,您可以按特定顺序异步测试脚本注入(inject):

主要想法是创建一个 API,允许您通过公开以下方法与要注入(inject)的脚本进行交互:

  • addScript:接收要加载的每个脚本的 URL 或 URL 列表。
  • load:运行任务以按指定顺序加载脚本。
  • reset:清除脚本数组,或者取消脚本加载。
  • afterLoad:每个脚本加载完成后执行的回调。
  • onComplete:所有脚本加载完成后执行的回调。

我喜欢Fluent Interface方法链 技术,所以我以这种方式构建了模块:

  scriptsLoader
.reset()
.addScript("script1.js")
.addScript(["script2.js", "script3.js"])
.afterLoad((src) => console.warn("> loaded from jsuLoader:", src))
.onComplete(() => console.info("* ALL SCRIPTS LOADED *"))
.load();

在上面的代码中,我们首先加载了"script1.js"文件,并执行了afterLoad()回调,接下来,对做同样的事情“script2.js”“script3.js” 并且在加载所有脚本后,执行 onComplete() 回调。

关于javascript - 动态添加的脚本标签的加载顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38839650/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com