我有一个装载机,想要研究异步和延迟时间。它是动态插入的外部脚本标记 - 无内联延迟。
起初我理解为什么异步表现为延迟 - 它在DOMContentLoaded之后执行。
使用2000个DOM元素,异步开始显示它可以在DOMContentLoaded之前执行。它从本地驱动器加载。通过从主机获取,在等待响应时执行脚本异步更有意义。这样才行。
然后我改为测试延迟和surprice ..现在我与笑话斗争为什么defer表现为异步 - 在DOMContentLoaded之前执行!
使用超过30秒的100000个DOM元素,脚本执行仍然发生在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之前,永远不应该执行延迟脚本。 现在我们有一个案例,在DOM出现在屏幕上之前,DOMContentLoaded会触发。怎么样?
编辑#1
当心DOMContentLoaded - 我想要“解析dom内容”!!! (这就是代码中的错误 - 或者在我看来) 纠正(感谢Pointy) - 用我的话来说......
在解析dom后执行延迟脚本,但dom仍在加载..当延迟脚本和最终事件完成时,DOMContentLoaded将触发。
所以它是我需要的某种“DOMContentParsed”。我找到的最好的是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。遗憾的是,readyState没有告诉WHEN dom被解析了!我也试过..
document.addEventListener('readystatechange', function() {
console.log(">>" + document.readyState);
});
这不会触发“加载”,因为它已经被解雇了,但它说“交互式”AFTER延迟脚本加载并说“完成”DOMContentLoaded(它们是否相同?)并且没有更多话要说。
我没有更多关于在/ dom解析时触发的方法或事件的idéa。它必须在继续加载其他dom之前,在其他时间之前获得正确的时间标记!
没有什么可以找到的!在Living Standard — Last Updated 15 April 2019第12.2.7节的第一点之前没有什么了。结束(甚至标题与我开玩笑):在任何脚本之前应该做“交互式”的readystatechange,但它实际上没有。为什么?
对我来说,似乎readyState在大于2000个元素的本地index.html上有一个错误,因为我可以在它说“交互”之前执行延迟脚本。现在,当把那个readyState放在脚本中时我已经很清楚了(我忘了)并且它说“正在加载”,这意味着在执行时仍会加载一个大的html:
的script.js
console.log("Execute script " + document.readyState);
结论:有时延迟表现为异步,异步表现为延迟
defer
上the MDN page for script elements属性的定义:
此布尔属性设置为向浏览器指示在解析文档之后但在触发DOMContentLoaded之前要执行脚本。
具有defer属性的脚本将阻止DOMContentLoaded事件触发,直到脚本加载并完成评估。
你所看到的是预期的行为。