在单页应用程序中有多个文件的情况下,Javascript异步延迟执行顺序
我正在努力提高页面的页面加载性能,这是在EmberJS上实现的 我正在考虑在我们的Javascript文件上使用在单页应用程序中有多个文件的情况下,Javascript异步延迟执行顺序,javascript,html,performance,asynchronous,deferred,Javascript,Html,Performance,Asynchronous,Deferred,我正在努力提高页面的页面加载性能,这是在EmberJS上实现的 我正在考虑在我们的Javascript文件上使用asyc和defer。所有其他优化都已经完成(将脚本移动到页面底部,将async和defer添加到分析标签等) 现在,根据ember cli规范,生成的index.html有两个脚本标记-一个供应商JS文件和一个应用程序JS文件 如果我要实现异步和延迟,我需要确保在加载我的应用程序JS文件之前加载我的供应商JS文件,以确保后者具有初始化应用程序所需的所有代码 我理解,使用async和d
asyc
和defer
。所有其他优化都已经完成(将脚本移动到页面底部,将async
和defer
添加到分析标签等)
现在,根据ember cli
规范,生成的index.html
有两个脚本标记-一个供应商JS文件和一个应用程序JS文件
如果我要实现异步
和延迟
,我需要确保在加载我的应用程序JS文件之前加载我的供应商JS文件,以确保后者具有初始化应用程序所需的所有代码
我理解,使用async
和defer
定义脚本时,获取和解析脚本的顺序是不同的
我的问题是:
如果在同一个页面中有多个JS文件,有没有办法按规定的顺序获取和执行它们?我在异步请求中寻找回调/承诺之类的东西,但是就实际的
脚本标记本身而言。我可以想出两种方法
a) 照你说的做。i、 e.有一个脚本标记,其中包含两个链接承诺,每个脚本标记创建一个新的脚本标记,将其附加到DOM,添加一个onload
事件函数,该函数将是承诺的resolve
函数,最后将其src
属性设置为资源的URL。当第一个承诺中的脚本加载时,第二个承诺应该执行并执行相同的操作
b) 走中间道路。将供应商文件放在头部,以便同步加载,并将应用程序文件放在文档的最底部,以便在完成所有其他操作后加载
在我看来,第一种选择是过度杀戮
编辑:示例a)
var p=新承诺(功能(解决、拒绝){
var scriptTag=document.createElement('script');
document.head.appendChild(scriptTag);
scriptTag.onload=解析;
scriptTag.src='URL_到_供应商_文件';
});
p、 然后(函数(){
var scriptTag=document.createElement('script');
document.head.appendChild(scriptTag);
scriptTag.src='URL_到_应用程序_文件';
};
注意:上面的例子可以写出来,不使用承诺,我可以想到两种方法
a) 照你说的做。i、 e.有一个脚本标记,其中包含两个链接承诺,每个脚本标记创建一个新的脚本标记,将其附加到DOM,添加一个onload
事件函数,该函数将是承诺的resolve
函数,最后将其src
属性设置为资源的URL。当第一个承诺中的脚本加载时,第二个承诺应该执行并执行相同的操作
b) 走中间道路。将供应商文件放在头部,以便同步加载,并将应用程序文件放在文档的最底部,以便在完成所有其他操作后加载
在我看来,第一种选择是过度杀戮
编辑:示例a)
var p=新承诺(功能(解决、拒绝){
var scriptTag=document.createElement('script');
document.head.appendChild(scriptTag);
scriptTag.onload=解析;
scriptTag.src='URL_到_供应商_文件';
});
p、 然后(函数(){
var scriptTag=document.createElement('script');
document.head.appendChild(scriptTag);
scriptTag.src='URL_到_应用程序_文件';
};
注意:上面的示例可以编写,并且不使用承诺自从这个问题第一次发布以来,事情可能已经变得更好了,但似乎在2019年,您可以推迟脚本,并按照脚本标记写入html文档的顺序处理它们您的vendor
脚本和main
脚本将使它们并行加载,而不是阻止html文档的解析,并在文档解析完成时按顺序进行处理
whatwg脚本文档的这一部分详细介绍了我将在这里总结的内容:
- 如果脚本的类型是“classic”(而不是
type=“module”
),并且元素具有src
属性,并且元素具有defer
属性,并且元素被标记为“parser inserted”,并且元素没有async
属性
- 然后将该元素添加到将要创建的脚本列表的末尾
尽快按与节点关联的顺序执行
准备脚本时脚本元素的文档
算法启动了
查看该链接以了解完整的详细信息,但实际上它似乎在说,延迟脚本将按照它们在html文档中解析的顺序进行处理
同意:
带有defer
属性的脚本将按以下顺序执行:
它们出现在文档中
另一个需要注意的要点(来自同一MDN文档):
带有defer
属性的脚本将阻止DOMContentLoaded
事件触发,直到脚本加载并完成计算
还值得注意的是,whatwg和MDN都没有提到将脚本标记放在html文档的头部或底部。如果所有脚本都具有defer
属性,则在html文档完成解析后,它们将按发生顺序进行处理。将脚本标记放在头部这意味着他们将在html文档解析过程的早期开始下载,而不是稍后,当他们被放在正文的底部时
<script>
var p = new Promise(function(resolve, reject) {
var scriptTag = document.createElement('script');
document.head.appendChild(scriptTag);
scriptTag.onload = resolve;
scriptTag.src = 'URL_to_vendor_file';
});
p.then(function() {
var scriptTag = document.createElement('script');
document.head.appendChild(scriptTag);
scriptTag.src = 'URL_to_application_file';
};
</script>