chaihongjun.me

javascript中的defer和async

######20190429更新

来源: https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html

图示:

javascript中的defer和async

绿色表示HTML解析过程,灰色表示HTML解析过程暂停,紫色表示脚本下载过程,粉色表示脚本执行过程。

没有defer和async的情况:

javascript中的defer和async

 

当使用script标签引入任意一个脚本文件,并且不带任何的属性(没有defer,也没有async)的时候页面渲染情况:

  1. 首选是HTML渲染

  2. 然后遇到script标签,开始下载脚本文件,同时HTML的解析工作被暂停

  3. JS脚本下载完,这个时候HTML的解析工作仍然是暂停状态

  4. JS脚本开始执行,这个时间内HTML的渲染也还是暂停的

  5. JS脚本执行完毕,被暂停的HTML解析开始恢复

可以看到一般情况下,JS的下载和解析都让HTML的解析暂停,HTML的解析行为被JS的下载和执行两个过程中断。

只有async的情况:

javascript中的defer和async

当有async的时候页面渲染情况:

  1. 首先是HTML渲染解析

  2. 然后遇到script引入的JS文件,这个时候脚本开始下载,同时HTML仍然继续解析,这个和前面的情况不同

  3. JS脚本文件下载完成,在JS脚本下载完成前,HTML的解析一直进行

  4. JS脚本开始执行,因为浏览器是单线程的,当JS在执行的时候,HTML的解析就被暂停了

  5. JS的执行完成了,被暂停的HTML解析恢复

只有defer的情况:

javascript中的defer和async

当有defer的时候页面渲染情况:

  1. 首先是HTML渲染解析

  2. 然后是遇到script引入的JS文件,这个时候JS脚本开始下载,和async一样,HTML的解析不受影响

  3. JS的下载完成了,但是并不是立即开始执行,而是继续执行HTML的解析

  4. HTML解析完成

  5. 最后JS脚本执行

综上所述,无论是async还是defer,都有一个异步下载的过程,脚本下载可以和HTML解析同步进行。唯一的区别是async会立即执行下载完的脚本,而defer则是等到HTML解析完毕再执行。

async和defer使用的一些规则:

  1. 如果JS脚本文件是一个独立模块没有依赖关系,那么可以使用async

  2. 如果JS脚本文件有依赖关系,被其他JS文件依赖或则依赖其他JS文件,则使用defer

  3. 如果JS脚本文件不大,然后本身依赖其他的async标注的脚本,可以直接以内联方式写脚本内容,而不用再通过async方式引入

#### 以下是以前的内容

对于熟知或者稍微了解javascript的人来说,或多或少的都听过同步加载和异步加载。说到同步加载和异步加载就不得不提及这么两个单词:

defer

async

这两个单词也会时常在一些网站源码出现。defer本身的含义就是推迟,延期,async则是异步的意思。我们来看几个例子:

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

以上三个都是加载script这个JS文件。

第一条没有defer和async,表示浏览器读取到这段代码的时候会立即加载并执行脚本内的内容。这里的立即也就是不等这个script后面的文档元素加载进来就执行它了。

第二条,只有async,字面意思就是异步的,所以script.js文件肯定是异步加载了。这里的异步其实是同时并行处理的意思。页面加载到这个script.js之后一边加载一边执行这个脚本,然后同时又继续加载之后的文档元素并渲染。

第三条,只有defer,字面意思是延迟,所以script.js肯定是延迟加载?延迟执行?实际defer情况下,也是一种异步加载的方式,只不过不再是同时并行处理。只是script.js的加载和后面的元素加载是同时进行,然后等后面的元素全部加载完毕渲染完毕了,script.js才去做执行。

下面是加载渲染执行时间的对比图:

javascript中的defer和async

蓝色是JS网络下载时间,绿色是JS解析时间,红色是JS执行时间。

从上面可以看到:

  1. 只有defer和async存在并行处理的情况,而且是在资源下载和页面解析的情况下。也就是一边下载页面一边也在解析页面内容。

  2. defer和async的唯一区别是红色部分,执行时间。defer延迟执行,等页面全部加载渲染完了再执行。

  3. async的执行时间是在网络下载完了之后,不管顺序如何,一旦JS下载完了就立即执行。

  4. async不考虑JS之间的依赖关系完全自由独立,典型的例子是谷歌和百度等统计代码。

知识共享许可协议本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。作者:柴宏俊»