這裡只討論支持並行下載的浏覽情況,大致分為兩種,一種是按加向DOM樹中加的順序執行,另一種按下載完成的先後順序執行;這樣如果js文件間有依賴關系的話,且是按下載順序執行,且在沒有緩存的情況下就會報錯(通常的情況下第一次執行會報錯,http返回狀態200,如果緩存未禁用,http狀態是304,就不會報錯了)
而ie就是按http下載完成的先後順序執行js代碼的,首先看下面的代碼:
復制代碼 代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Model</title>
<meta http-equiv="Content-language" content="zh-CN" />
</head>
<body>
<div id="page">
</div><!-- Page end! -->
<script type="text/javascript">
//<![CDATA[
var js = document.createElement('script');
js.type = 'text/javascript';
js.src = 'alert.js';
if(js.readyState){
js.onreadystatechange = function(){
if (js.readyState == "loaded" || js.readyState == "complete"){
alert(js.readyState);
document.getElementsByTagName('head')[0].appendChild(js);
}
};
}else{
document.getElementsByTagName('head')[0].appendChild(js);
js.onload = function(){
alert('loaded not in ie!');
};
}
//]]>
</script>
</body>
</html>
其中動態加載的alert.js文件中內容為:alert('in alert.js');
經過測試(ie8),可以發現彈出的內容先後為:loaded、in alert.js、complete
查資料可得ie下向DOM中添加script時有onreadystatechange事件(其它浏覽器有onload事件),而事件中js.readyState的狀態變化為:loading(下載中)、loaded(下載完成)、complete(代碼執行完成)
從代碼中可以看出我是在事件中才向DOM中添加創建的scrip結點的……
因此可以得出ie在創建scrip結點並給src賦值時就開始有http下載了,這與其它浏覽器完全不同(其它浏覽器是要把script結點加到DOM中才會有http下載的),而把scrip結點向DOM樹中添加後才開始執行代碼。
有了這些結論我們就可以解決ie下並行下載順序執行的問題了;有兩種方案:一種是邊下載邊順序執行,另一種是全下載完再順序執行。
兩種各有好處,這裡給出後一種情況的代碼(loader.js):
復制代碼 代碼如下:
/*
* Author: JaiHo
*/
(function(window){
var DOMLoader = (function(){
var DOMLoader = function(){
return new DOMLoader.prototype.init();
};
DOMLoader.prototype = {
jsList:[], js_all:0, loaded_js:0,
head:document.getElementsByTagName('head')[0],
init:function(){ },
create_node:function(src){
var js = document.createElement('script');
js.type = 'text/javascript';
this.bindWait(js);
this.jsList[this.jsList.length] = js;
js.src = src;
},
loadJS:function(list){
len = list.length;
for(var i=0; i<len; i++){
if( i==len-1 )
this.js_all = len;
this.create_node(list[i]);
}
return this;
},
bindWait:function(js){
if(arguments.callee.caller!==this.create_node) return;
var that = this;
if(js.readyState){
js.onreadystatechange = function(){
if( js.readyState == 'loaded' ){
that.loaded_js++;
if( that.js_all == that.loaded_js ){
that.head.appendChild( that.jsList.shift() );
}
}
if ( js.readyState == "complete" ){
js.onreadystatechange = null;
if( that.jsList.length ){
that.head.appendChild( that.jsList.shift() );
}
}
};
}else{
js.onload = function(){
alert('not in ie!');
};
}
return this;
}
};
DOMLoader.prototype.init.prototype = DOMLoader.prototype;
return window.DOMLoader = DOMLoader;
})();
})(window);
測試例子如下:
復制代碼 代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>Loader</title>
<meta http-equiv="Content-language" content="zh-CN" />
<style type="text/css" media="all">
</style>
</head>
<body>
<div>
</div>
<script type="text/javascript" src="loader.js"></script>
<script type="text/javascript">
//<![CDATA[
window.onload = function(){
var loader = DOMLoader();
loader.loadJS([ 'json.js', 'jquery-1.5.min.js', 'test.js' ]);
};
//]]>
</script>
</body>
</html>
可以看出加載的3個js文件是並行下載的。
對於其它浏覽器有動態加載js文件的並行下載和順序執行問題的情況,目前還沒有相對完美的解決方案(如果有了請指教一下。。),單從這個方面,個人覺得ie的這個onreadystatechange事件方案相對好些。