html5中script的async屬性
我興奮於html5的原因之一是一些久久未能實現的特性現在可以真正運用於實際項目中了. 如我們使用placeholder效果蠻久了但是那需要javascript來實現. 目前firefox和chrome都是實現了script標簽的async屬性.這個新的屬性能讓我們以一種更 簡單的方式防止瀏覽器阻塞,在這之前我們需要用一些javascript小竅門來解決這個問題.
async - html代碼
<script async src="myscript.js" onload="myInit()"></script>
就像我之前提到的,加個屬性很容易.
defer - html代碼
script標簽也有個defer屬性,目前所有瀏覽器都已實現, 在firefox和chrome的早期版本沒有實現此屬性,IE從一開始就支持此屬性.
<script defer src="myscript.js" onload="myInit()"></script>
async & defer - 它們的區別是什么
帶有async或者defer的script都會立刻下載並不阻塞頁面解析,而且都提供一個可選的onload事件處理, 在script下載完成后調用,用於做一些和此script相關的初始化工作.它們的不同之處在於script執行的 時機.帶有async的script,一旦下載完成就開始執行(當然是在window的onload之前).這意味着這些script 可能不會按它們出現在頁面中的順序來執行,如果你的腳本互相依賴並和執行順序相關,就有很大的可能出問題, 例如變量或者函數未定義之類的錯誤. 而對於帶有defer的script,它們會確保按在頁面中出現的順序來執行,它們執行的時機是在頁面解析完后,但在 DOMContentLoaded事件之前.(親測下來確實如此,下面會給出我的測試用例和說明)
目前哪些瀏覽器支持defer和async
目前來看,最新版本的firefox和chrome(還有同樣webkit內核的safari,本人機器上的版本是ff6,chrome15dev-m,IE9)都已支持這兩個屬性,也都支持script的load事件. IE的話對於defer是一直都支持的,async屬性IE6~9都沒有支持(IE10毫無疑問的會支持),onload是在IE9中新加入的屬性.
--------------------下面來一些我對defer,async,onload的測試用例------------------------------
寫了簡單的四段腳本用於測試
/** script1 **/
window.ns = {};
window.ns.delay = function(n) {
var start = Number(new Date()),
wait = n * 1000;
while(true) {
var end = Number(new Date());
if(end-start >= wait) {
break;
}
}
console.log("take " + n + " seconds to execute");
};
console.log("create a namespace named ns");
document.addEventListener("DOMContentLoaded", function() {
console.log("oh yeah, Dom Ready!");
}, false);
window.addEventListener("load", function() {
console.log("oh yeah, All Resources Loaded!");
}, false);
/** script2 **/
if(window.ns) {
window.ns.one = 'ONE';
console.log('window.ns.one:' + window.ns.one);
window.ns.delay(2);
} else {
console.log('oops...');
}
/** script3 **/
if(window.ns && window.ns.one) {
window.ns.two = "TWO";
console.log('window.ns.two:' + window.ns.two);
window.ns.delay(2);
} else {
console.log('oops...');
}
/** script4 **/
if(window.ns && window.ns.two) {
window.ns.three = "THREE";
console.log('window.ns.three:' + window.ns.three);
} else {
console.log('oops...');
}
用於測試的基本html頁面
<!DOCTYPE htm>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<script type="text/javascript" src="script1.js"></script>
<script type="text/javascript" src="script2.js"></script>
<script type="text/javascript" src="script3.js"></script>
<script type="text/javascript" src="script4.js"></script>
</head>
<body>
<img src="http://img9.zol.com.cn/desk_pic/big_452/451134.jpg"
width="200" height="200" alt="a big image of beauty"/>
</body>
</html>
剩下的事情就是在script上加上defer和async進行測試
1.無defer和async屬性
<script type="text/javascript" src="script1.js"></script> <script type="text/javascript" src="script2.js"></script> <script type="text/javascript" src="script3.js"></script> <script type="text/javascript" src="script4.js"></script>
我們先看資源加載瀑布圖(firefox和chrome類似,IE9的有點奇怪):

看得出來image的下載被script的執行給阻塞了.
console輸出如下:

2.都給上defer屬性
<script type="text/javascript" src="script1.js" defer></script> <script type="text/javascript" src="script2.js" defer></script> <script type="text/javascript" src="script3.js" defer></script> <script type="text/javascript" src="script4.js" defer></script>
資源加載瀑布圖:

看得出來所有資源進行了並行下載,沒有阻塞img的情況
console輸出和第1個測試的輸出一致,IE9和chrome是如此,但是奇怪的是Firefox在這種情況下, 居然沒有觸發DOMContentLoaded事件,即輸出少了Dom Ready!一行


3.部分給上defer屬性
<script type="text/javascript" src="script1.js"></script> <script type="text/javascript" src="script2.js" defer></script> <script type="text/javascript" src="script3.js" ></script> <script type="text/javascript" src="script4.js" defer></script>
因為這里面4個script都是有執行順序依賴的,所以如果defer屬性不加選擇的添加的話,就會出麻煩, 本例中,script1和script3就會先執行,script2和script4晚執行,就出現錯誤了
console輸出如下:

4.都給上async屬性
<script type="text/javascript" src="script1.js" async></script> <script type="text/javascript" src="script2.js" async></script> <script type="text/javascript" src="script3.js" async></script> <script type="text/javascript" src="script4.js" async></script>
IE9根本不支持這個,所以不用測試. Firefox和chrome都是第一次訪問時,出現了異步執行的情況, 之后有緩存的話script的執行順序貌似得到了維護.資源時間瀑布上 表現出的是預期的情況,即沒有給其他資源的下載造成阻塞

Chrome中第一次訪問,console輸出如下,無論出錯與否chrome和firefox的DOMContentLoaded均未未觸發

5.部分給async屬性
<script type="text/javascript" src="script1.js" async></script> <script type="text/javascript" src="script2.js"></script> <script type="text/javascript" src="script3.js"></script> <script type="text/javascript" src="script4.js" async></script>
這種情況的效果在chrome下比較明顯,分析起來也很簡單,4個script都是並行下載,但是如果script1和script4下完后立馬執行, 很顯然就破環了它們之間的依賴關系,可惜的是這種競爭的現象在Firefox中出現的概率比較低,可能跟firefox的緩存機制有關系
chrome的console輸出如下:

關於script的onload屬性會另外寫一篇文章來記錄.
最后,如果您有什么疑問或者發現文中有錯誤,歡迎指出,共同進步
