为什么将defer显示为async而将async显示为defer?正确获取“ dom解析事件”!但是没有吗?

时间:2019-04-21 13:56:35

标签: javascript performance dom-events web-performance

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

起初,我需要弄清楚为什么 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

1 个答案:

答案 0 :(得分:2)

the MDN page for script elementsdefer属性的定义:

  

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

     

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

您所看到的是预期的行为。

相关问题