javascript的defer和async(转载)
http://ued.ctrip.com/blog/?p=3121
我们常用的javascript标签,有两个和性能、js文件下载执行相关的属性:defer和async
defer的含义【摘自https://developer.mozilla.org/En/HTML/Element/Script】
| This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed. |
async的含义【摘自https://developer.mozilla.org/En/HTML/Element/Script】
| Set this Boolean attribute to indicate that the browser should, if possible, execute the script asynchronously. |
defer
对于defer,我们可以先思考一个情况。一个页面如果有N个外链的脚本,放在head中,那么,当加载脚本时会阻塞页面的渲染,也就是常说的空白。在简单的开发环境中,我们可能只要将源代码中的外链脚本位置换一下就ok了。可是面对越来越复杂的开发环境,前端同事如果要后台开发同事调整一下脚本的位置,可能会花费大量的沟通成本和开发成本。我在去年的一个项目中就遇到过此类情况,当然也很感谢当时的后台开发同事的配合,他们都辛辛苦苦的调整了脚本的位置,解决了空白的问题。
那么可以让这个成本降到最低吗?那么我们可以使用defer这个属性。
如果一个script加了defer属性,即使放在head里面,它也会在html页面解析完毕之后再去执行,也就是类似于把这个script放在了页面底部。
关于defer有两个demo:
简单介绍一下这个demo,一共引用了3个js和1个css,为了能更好的展示defer的效果,第二个js-2.php是延迟了3秒返回的。1.js会在页面中生成一个值为1的input框,2.php会生成值为2的input框,3.js会生成值为3的input框。一方面我们需要观察页面渲染的时间,另一方面我们也要看一下js是否顺序执行了。
下图是without_defer.html的效果,从瀑布图可以看出,domready和onload的时间都在6s左右,因为需要等待2.php的返回才能渲染页面。如果你访问上面的例子,可以看出,页面要等6s的时间才会呈现出来,6s之前都是空白。

那么如果我们为每个js都加上defer属性,请看下面两张图
第一张是在加载过程中截取的,可以看到一旦有了defer属性,虽然有资源2.php需要等待,但是仍然会继续渲染页面,加载后续的js和css等资源文件。对比上面的情况,可以看到domready的时间明显提前,如果你访问demo地址,会发现页面会照常渲染出来,只不过2.php里面的内容会延迟执行。


从上面的对比可以看出,对于defer,我们可以认为是将外链的js放在了页面底部。js的加载不会阻塞页面的渲染和资源的加载。不过defer会按照原本的js的顺序执行,所以如果前后有依赖关系的js可以放心使用。
Async
对于async,这个是html5中新增的属性,它的作用是能够异步的加载和执行脚本,不因为加载脚本而阻塞页面的加载。一旦加载到就会立刻执行。那async和defer有什么不同之处呢?我们还是先看async的两个demo
demo的效果和上面描述的一样。
下图是without async的瀑布图,和没有defer的情况是一样的。domready和load的时间都因为一个js的延迟而延迟了。
我们再看一下有async属性的情况,和defer一样,会等待的资源不会阻塞其余资源的加载,也不会影响页面的加载。但是有一点需要注意下,在有async的情况下,js一旦下载好了就会执行,所以很有可能不是按照原本的顺序来执行的。如果js前后有依赖性,用async,就很有可能出错。


Difference
这篇文章中总结了defer和async的相同点和区别。
Both
asyncanddeferscripts 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. The difference betweenasyncanddefercenters around when the script is executed. Eachasyncscript executes at the first opportunity after it is finished downloading and before the window’s load event. This means it’s possible (and likely) thatasyncscripts are not executed in the order in which they occur in the page. Thedeferscripts, 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’sDOMContentLoadedevent.
Wrapping it up
在上述的基础上,我根据实际使用的情况总结了一下defer和async的特征。
相同点:
- 加载文件时不阻塞页面渲染
- 对于inline的script无效
- 使用这两个属性的脚本中不能调用document.write方法
- 有脚本的onload的事件回调
区别点:
- html的版本html4.0中定义了defer;html5.0中定义了async
- 浏览器
Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari Basic support 1.0 1.0 (1.7 or earlier) (Supported) (Supported) (Supported) asyncattribute(Supported) 3.6 (1.9.2) 10 – (Supported) deferattribute(Supported) 3.5 (1.9.1) 4 – (Supported) - 执行时刻
每一个async属性的脚本都在它下载结束之后立刻执行,同时会在window的load事件之前执行。所以就有可能出现脚本执行顺序被打乱的情况;每一个defer属性的脚本都是在页面解析完毕之后,按照原本的顺序执行,同时会在document的DOMContentLoaded之前执行。
摘自【http://dev.w3.org/html5/spec/Overview.html#attr-script-async】
There are three possible modes that can be selected using these attributes. If the async attribute is present, then the script will be executed asynchronously, as soon as it is available. If the async attribute is not present but the defer attribute is present, then the script is executed when the page has finished parsing. If neither attribute is present, then the script is fetched and executed immediately, before the user agent continues parsing the page.
简单的来说,使用这两个属性会有三种可能的情况
- 如果async为true,那么脚本在下载完成后异步执行。
- 如果async为false,defer为true,那么脚本会在页面解析完毕之后执行。
- 如果async和defer都为false,那么脚本会在页面解析中,停止页面解析,立刻下载并且执行,
最后给一点个人的建议,无论使用defer还是async属性,都需要首先将页面中的js文件进行整理,哪些文件之间有依赖性,哪些文件可以延迟加载等等,做好js代码的合并和拆分,然后再根据页面需要使用这两个属性。
本文another链接:http://feifeipan.sinaapp.com/?p=51
=====华丽丽的分割线=========
对于znxds提出的IE下的工作,我针对FF和IE6、IE7、IE8下面做了比较。
Firefox中,inline的defer是没有效果的;outer的defer会在页面最底部执行。
IE8.0中,inline和outer的defer是起作用的,都会延迟到页面底部,排在其他非defer的js后面执行
IE7.0的情况,和IE8.0一致。
IE6.0中,关于defer inline js,要区分是在head中还是在body中。在head中defer inline js会在遇到body之后优先执行,而在body中的defer inline js会在body结束之前执行;关于defer outer js, 依然是在页面最后执行。
所以可以看出,defer的outer js在各种浏览器中表现一致;defer的inline js在IE6中比较特殊,head和body中的顺序不一样,IE7和IE8会延迟到页面底部执行,在Firefox中无效。
本文作者:小灰灰 转载请注明来自:携程UED
javascript的defer和async(转载)的更多相关文章
- javascript的defer和async的区别。
我们常用的script标签,有两个和性能.js文件下载执行相关的属性:defer和async defer的含义[摘自https://developer.mozilla.org/En/HTML/Elem ...
- JavaScript 的 defer 与 async
当解析器遇到 script 标签时,文档的解析将停止,并立即下载并执行脚本,脚本执行完毕后将继续解析文档.但是我们可以将脚本标记为 defer,这样就不会停止文档解析,等到文档解析完成才执行脚本,也可 ...
- JavaScript标记上的defer与async的作用与区别
当浏览器遇到 script 标签时,文档的解析将停止,并立即下载并执行脚本,脚本执行完毕后将继续解析文档.但是我们可以将脚本标记为 defer,这样就不会停止文档解析,等到文档解析完成才执行脚本,也可 ...
- javascript中的defer和async学习+javascript执行顺序
一.defer和async 我们常用的script标签,有两个和性能.js文件下载执行顺序相关的属性:defer和async defer的含义[摘自https://developer.mozilla. ...
- javascript延迟加载及异步(defer和async)
一直以来写代码的时候的常用习惯就是吧所有的js文件直接加载在文档的head标签里面,在写js文件的时候有时候获取一些文件对象的时候为空对象,这是由于文档结构还没有加载完,但是js文件已经加载完.也就是 ...
- 浏览器环境下JavaScript脚本加载与执行探析之defer与async特性
defer和async特性相信是很多JavaScript开发者"熟悉而又不熟悉"的两个特性,从字面上来看,二者的功能很好理解,分别是"延迟脚本"和"异 ...
- 【javascript基础】 JavaScript defer和async区别
defer该属性用来通知浏览器,这段脚本代码将不会产生任何文档内容.例如 JavaScript代码中的document.write()方法将不会骑作用,浏览器遇到这样的代码将会忽略,并继续执行后面的代 ...
- 带你玩转prefetch, preload, dns-prefetch,defer和async
现代浏览器性能优化-JS篇 众所周知,JS的加载和执行会阻塞浏览器渲染,所以目前业界普遍推荐把script放到</body>之前,以解决js执行时找不到dom等问题.但随着现代浏览器的普及 ...
- script标签中defer和async属性的区别
这篇文章来源于JS高级程序设计第三版中关于script标签的介绍,结合查阅的资料写下的学习笔记. 向html页面中插入javascript代码的主要方法就是通过script标签.其中包括两种形式,第一 ...
随机推荐
- hdu 3986(最短路变形好题)
Harry Potter and the Final Battle Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65536/6553 ...
- HDU5877Weak Pair
Weak Pair Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 26 ...
- slam学习足迹
1.slam入门介绍 2.齐次坐标系 3.贝叶斯滤波 均值:平均值 标准差:样本的集中程度/分散度 方差:标准差的平方 协方差:不同维度之间的关系(相关度) 协方差矩阵:多维度之间的关系(相关度) 4 ...
- rapidxml读取包含中文路径的xml解析错误的解决方法
from http://blog.csdn.net/qinwei4072880/article/details/38865179 1.rapidxml不支持中文路径. 2.rapidxml不支持Uni ...
- Docking For WPF–AvalonDock
桌面程序的应用,不可避免的就会用到大量的布局控件,之前的一个项目也想过去做类似于Visual Studio的那种灵活的布局控件,也就是界面上的控件能够实现拖拽放置.隐藏.窗口化等一系列的操作,但由于开 ...
- dedecms让channelartlist标签支持currentstyle属性方
把dedecms中用channelartlist当导航的站很普遍,但是有的站需要用到当前页中导航样,就是随着不同的页面,导航样式也随着变化. 首先打开include\taglib\channelart ...
- 探秘 flex 上下文中神奇的自动 margin
为了引出本文的主题,先看看这个问题,最快水平垂直居中一个元素的方法是什么? 水平垂直居中也算是 CSS 领域最为常见的一个问题了,不同场景下的方法也各不相同,各有优劣.嗯,下面这种应该算是最便捷的了: ...
- Python--图像处理(2)
skimage提供了io模块,顾名思义,这个模块是用来图片输入输出操作的.为了方便练习,也提供一个data模块,里面嵌套了一些示例图片,我们可以直接使用. 引入skimage模块可用: 1 from ...
- Esper epl语句实验
基础代码见下,下文列举的实验都是在此程序基础上改动. all,snapshot,first String epl = "select * from appTable.win:time(5 s ...
- 搭建rocketMq环境
大体流程按照文章https://blog.csdn.net/wangmx1993328/article/details/81536168逐步搭建,下面列出踩过的一些坑 1,自己的阿里云服务器端口没开放 ...