jtwang7 / JavaScript-Note

JavaScript学习笔记
10 stars 2 forks source link

JS - defer 与 async #35

Open jtwang7 opened 3 years ago

jtwang7 commented 3 years ago

defer & async

浏览器加载 script 脚本的三种场景:

  1. 同步加载 script

    <script src="script.js">

    没有 defer 或 async,浏览器会立即加载并执行指定的脚本,它会停止解析渲染后续的文档元素。

  2. async 异步加载 script

    <script async src="script.js">

    有 async,加载和渲染后续文档元素的过程将和 script.js 的加载并行进行(异步)。在脚本加载阶段,浏览器会继续解析文档元素,一旦脚本下载完成,就会转而先执行脚本文件,暂停解析文档元素(GUI 与 JS 互斥)

  3. defer 异步加载 script

    <script defer src="myscript.js">

    有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。脚本加载不影响文档元素的解析,但脚本的执行始终要等到文档元素全部解析完成后执行。

    从实用角度来说,首先把所有脚本都丢到</body>之前是最佳实践,因为对于旧浏览器来说这是唯一的优化选择,此法可保证非脚本的其他一切元素能够以最快的速度得到加载和解析。

总结

defer 和 async 在网络读取(下载脚本)时行为类似,均是异步的(相较于 HTML 解析) 两者区别在于:

  1. 脚本异步下载完之后执行的时机:defer 会在所有文档元素解析完成后,DOMContentLoaded 事件触发之前执行;async 会在脚本一步下载完成后立刻执行。
  2. 脚本异步下载完之后的加载顺序:defer 按照脚本开始下载的顺序执行脚本;async 则是乱序执行,因为 async 脚本的加载和执行是紧挨着执行的,因此哪个脚本先加载完成就会先执行哪个。

    defer 按照脚本声明顺序执行,async 按照脚本加载完成的先后顺序执行。

仔细想想,async 对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的