首先要知道两者是什么?
async和defer都是script标签的属性,用于在不阻塞页面文档解析的前提下,控制脚本的下载和执行。
接下来我们需要了解页面的文档渲染机制
1.浏览器通过http协议请求服务器,获取html文档并从上至下解析,构建DOM;
2.在构建DOM过程中,如果遇到外联样式声明和脚本声明,则会暂停文档解析,创建新的网络连接,并开始下载样式文件和脚本文件;
3.待样式文件下载完成,开始构建CssDOM;脚本文件下载完成之后,解释并执行,继续解析文档构建DOM;
4.完成文档解析之后,将DOM和CssDOM进行关联和映射,最后将视图渲染到浏览器窗口。
在渲染过程中,js脚本文件下载和执行与文档解析是同步进行的,如果js出现堵塞,整个页面的渲染将会被影响,出现白屏。fouc等现象,影响用户体验。所以我们可以用defer和async控制脚本异步加载正好解决了这一问题存在。
defer作用:用于开启新的线程下载脚本文件,并使脚本在文档解析完成后执行。
async作用:用于异步下载脚本文件,下载完成之后立即解释执行代码。
我们可以通过下图更加清楚的了解两者的执行和DOMConentLoaded、load事件的关系:
上图让我们很明显看到了defer和async的脚本下载都是异步执行,区别主要是 defer是在页面解析完成之后执行脚本,async是在下载完脚本之后立即执行。
基本语法
<script async src="script.js" ></script>
<script defer src="script.js" ></script>
两者使用需要注意的地方
defer:
1.defer只适用于外联脚本,如果script标签没有指定src属性,只是内联脚本,不要使用defer;
2:如果有多个声明defer的脚本,则会按照顺序下载执行;
3:defer脚本会在DOMContentLoaded和load事件之前执行。
async:
1.和defer一样,只适用于外联脚本;
2.如果有多个声明async的脚本,下载和执行也是异步的,但不能确保彼此的先后顺序;
3.async会在load事件之前执行,但并不确保与DOMContentLoad的执行先后顺序;