为什么它将延迟显示为异步,异步显示为延迟?把"dom parsed event"对了!但是没有吗?



我有一个加载器,想研究异步和延迟计时。它是动态插入的外部脚本标记 - 无内联延迟。

起初,我为理解为什么异步表现为延迟而斗争 - 它在 DOMContentLoaded 之后执行

对于 2000 个 DOM 元素,异步启动显示它可以在 DOMContentLoaded 之前执行。它从本地驱动器加载。使用从主机获取,在等待响应时异步执行脚本更有意义。这样就行了。

然后我改为测试延迟和超价..现在我和这个笑话作斗争,为什么defer 表现为异步 - 在 DOMContentLoaded 之前执行

由于 100000 个 DOM 元素占用了 30 多个时间,脚本执行仍然发生在 DOMContentLoaded 之前。怎么了?

这是我测试的相关部分...

装载机.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");

脚本.js

console.log("Execute script");

索引.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将触发。

所以这是我需要的某种"DOMContentParsed"。我发现的最好的是readystatechange事件document.readyState...

让我们用这一行扩展加载器.js:

s.onload = function(){ console.log(document.readyState) }

有了足够的dom,它就会在Chrome和Firefox控制台中显示:

Fetch script
Execute script
loading
DOMContentLoaded

这意味着延迟脚本在 DOM 加载时执行! 是的,是的 - 它正在加载,直到 DOMContentLoaded。可惜 readyState 没有告诉 dom 何时被解析!我也试过..

document.addEventListener('readystatechange', function() {
console.log(">>" + document.readyState); 
});

这不会在"加载"时触发,因为它已经触发,但它在延迟加载脚本后说"交互式"并说"完成",其中 DOMContentLoaded 在哪里(它们是一样的吗?),它没有更多要说的。

我没有更多的 idéa 在 dom 解析时/当 dom 解析时触发的方法或事件。必须在继续加载其他 dom 内容之前,以便在其他时间之前获得正确的计时标记!

没有什么可找的了!在生活标准的第一点之前没有更多 — 最后更新于 2019 年 4 月 15 日 第 12.2.7 节 结尾(甚至是标题与我开玩笑):它是readystatechange,应该在任何脚本之前进行"交互式",但实际上并非如此。为什么?

对我来说,readyState 似乎在本地索引上有一个错误.html大于 2000 个元素,因为我可以在它说"交互式"之前执行延迟脚本。现在肯定很清楚,当把那个readyState放在脚本中时(我忘了),它说"加载",这意味着一个大的html在执行时仍在加载:

脚本.js

console.log("Execute script " + document.readyState);

结论有时延迟表现为异步,异步行为为延迟

MDN 页面上脚本元素的defer属性定义:

此布尔属性设置为向浏览器指示脚本应在分析文档之后但在触发 DOMContentLoaded 之前执行。

具有 defer 属性的脚本将阻止 DOMContentLoaded 事件触发,直到脚本加载并完成评估。

您看到的是预期的行为。

最新更新