script异步加载async和defer异同

用法

<script async src="myAsync.js"></script>
<script defer src="myDefer.js"></script>

异步加载的好处

如果不选择异步加载script的话,当浏览器在解析HTML源文件时如果遇到外部的script,那么解析过程会暂停,并发送请求来下载script文件,只有script完全下载并执行后才会继续执行DOM解析。
而如果选择异步加载的话:

Both async and defer scripts begin to download immediately without pausing the parser and both support an optional onload handler to address the common need to perform initialization which depends on the script.

可以在不影响DOM解析的情况下,下载script脚本。并且可以加上onload属性用来定义当完成script脚本下载之后的初始化操作。
<script async src="myAsync.js" onload="initFunc()"></script>

相同点

  • 可以在不影响DOM解析的情况下,下载script脚本。
  • 并且可以加上onload属性用来定义当完成script脚本下载之后的初始化操作。

不同点

The difference between async and defer centers around when the script is executed. Each async script executes at the first opportunity after it is finished downloading and before the window’s load event. This means it’s possible (and likely) that async scripts are not executed in the order in which they occur in the page. The defer scripts, on the other hand, are guaranteed to be executed in the order they occur in the page. That execution starts after parsing is completely finished, but before the document’s DOMContentLoaded event.

  • async:下载完成,立刻执行(意味如果有多个async外部脚本,哪个先被下载好就先执行哪个,不会按照写在页面上的顺序来执行);在windowload事件之前。
  • defer:按照写在页面上的顺序来执行;在documentDOMContentLoaded事件之前。

例子

没有异步:


异步之后:

实践

蓝色线代表网络读取,红色线代表执行时间,这俩都是针对脚本的;绿色线代表 HTML 解析。

此图告诉我们以下几个要点:

  • deferasync 在网络读取(下载)这块儿是一样的,都是异步的(相较于 HTML 解析)
  • 它俩的差别在于脚本下载完之后何时执行,显然defer是最接近我们对于应用脚本加载和执行的要求的
  • 关于defer,此图未尽之处在于它是按照加载顺序执行脚本的,这一点要善加利用
  • async则是一个乱序执行的主,反正对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行
  • 仔细想想,async 对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics

参考

http://segmentfault.com/q/1010000000640869 @nightire
http://segmentfault.com/blog/miser/1190000000339118 @miser
https://www.webkit.org/blog/1395/running-scripts-in-webkit/