我有一个加载器,想研究异步和延迟时间。这是一个动态插入的外部脚本标签-无内联延迟。
起初,我需要弄清楚为什么 async表现为延迟-它在DOMContentLoaded 之后执行。
使用2000个DOM元素,异步开始显示它可以在DOMContentLoaded之前执行。它是从本地驱动器加载的。通过从主机获取,在等待响应时异步执行脚本更为有意义。这样行得通。
然后我更改为测试延期和超价。.现在我开玩笑说为什么 defer表现为异步-在DOMContentLoaded之前执行!
有100000个DOM元素占用了30多秒钟,脚本执行仍然在DOMContentLoaded之前发生。怎么了?
这是我用...测试过的相关部分
loader.js
window.addEventListener('DOMContentLoaded', function() {
console.log("DOMContentLoaded");
});
var s = document.head.appendChild(document.createElement('script'))
// s.async = true; s.defer = false;
s.async = false; s.defer = true;
s.src = "script.js"
console.log("Fetch script");
script.js
console.log("Execute script");
index.html
<html>
<head>
<script src="loader.js"></script>
</head>
<body>
<script> window.ti = performance.now() </script>
--- put here every html you can find ---
<script>
var n = document.getElementsByTagName('*').length
var t = parseInt(performance.now() - ti) / 1000
document.write("<br>Parsed " + n + " elements in " + t + " s ")
</script>
</body>
</html>
在FF和Chrome中安装控制台
Fetch script
Execute script
DOMContentLoaded
在准备好使用DOM之前,不应执行延迟脚本。
现在,我们有一个情况,即DOMContentLoaded在DOM不在屏幕上之前触发。怎么样?
编辑#1
当心DOMContentLoaded-我想“解析dom内容” !!!
(这就是代码中的错误-或在我的脑海中)
更正(感谢Pointy)-用我的话...
延迟的脚本在dom解析后执行,但dom仍在加载。当延迟的脚本和最终事件完成时,将触发DOMContentLoaded。
因此,我需要某种“ DOMContent 已解析”。我发现最好的是 readystatechange事件和 document.readyState ...
让我们在以下行扩展loader.js:
s.onload = function(){ console.log(document.readyState) }
具有足够的dom,它会在Chrome和Firefox控制台中显示:
Fetch script
Execute script
loading
DOMContentLoaded
这意味着在DOM is loading期间执行延迟脚本! 是是-它正在加载,直到DOMContentLoaded。可耻的是,stateState不会告诉您何时解析dom!我也尝试过。
document.addEventListener('readystatechange', function() {
console.log(">>" + document.readyState);
});
这不会在“正在加载”时触发,因为它已经被触发,但是在延迟加载脚本后说“交互式”,并在DOMContentLoaded所在的位置说“完成”(它们是相同的吗?),这里就不多说了。
我不再有在dom解析时/触发时触发的方法或事件的IDéa。必须在继续加载其他dom东西之前,在其他时间之前获得正确的时间标记!
没有其他可以找到的了! Living Standard — Last Updated 15 April 2019第12.2.7节中的第一点之前没有其他内容了(甚至是和我开玩笑的话): readystatechange应该在任何之前进行“交互”脚本,但实际上不是。。为什么?
对我来说,似乎readyState在本地index.html上的错误大于2000个元素,因为我可以在它说“交互式”之前执行一个延迟的脚本。现在也很清楚何时也将readyState放到脚本中(我忘了),它说“正在加载”,这意味着在执行时仍在加载一个大html:
script.js
console.log("Execute script " + document.readyState);
结论:有时defer表现为异步,而async表现为defer
答案 0 :(得分:2)
the MDN page for script elements上defer
属性的定义:
此布尔属性设置为向浏览器指示脚本应在文档解析后但在触发DOMContentLoaded之前执行。
具有defer属性的脚本将阻止触发DOMContentLoaded事件,直到脚本加载并完成评估为止。
您所看到的是预期的行为。