JavaScript 无阻塞加载脚本与异步脚本整合
<script type="text/javascript">
<!--
$_E = {
//单个脚本加载使用的接口,不理有序和无序
loadScript : function(url, onload) {$_E.loadScriptDomElement(url, onload);},
//多个脚本下载使用的接口,有序,并且区分域
loadScripts : function(urls, onload) {
var E = $_E;
var len = urls.length;
var bDifferent = false;//判断是否脚本处于不同域的标志
//判断是否加载的脚本不同域
for (var i = 0; i < len; i++) {
if (E.differentDomain(urls[i])) {bDifferent = true;break;}
}
var loadFunc = E.loadScriptXhrInjection;//默认使用loadScriptXhrInjection方法
var userAgent = navigator.userAgent;
//不同域
if (bDifferent) {
//如果是Firefox或者Opera浏览器,则采取loadScriptDomElement方法,否则则采用loadScriptDocWrite
if ( -1 != userAgent.indexOf('Firefox') || -1 != userAgent.indexOf('Opera')) {
loadFunc = E.loadScriptDomElement;
} else {
loadFunc = E.loadScriptDocWrite;
}
}
//进行多脚本加载
for (var i = 0; i < len; i++) {
loadFunc(urls[i], ( i+1 == len ? onload : null ), true);
}
},
//判断各个脚本是否不同域
differentDomain : function(url) {
//判断是否存在协议和主机头部,存在,则检测是否不同域,否则直接返回同域
if (0 == url.indexOf('http://') || 0 == url.indexOf('https://')) {
var mainDomain = document.location.protocol + "//" + document.location.host + "/";
return (0 !== url.indexOf(mainDomain));
}
return false;
},
//动态脚本注入方式,支持并行加载,支持跨域,在Opera和Firefox中是有序下载
loadScriptDomElement : function(url, onload) {
var domscript = document.createElement("script");
domscript.type = "text/javascript";
domscript.src = url;
if (onload) {
domscript.onloadDone = false;
domscript.onload = onload;
domscript.onreadystatechange = function(){
if (("loaded" == domscript.readyState || "completed" == domscript.readyState) && !domscript.onloadDone) {
domscript.onloadDone = true;
domscript.onload();
}
}
}
document.getElementsByTagName("head")[0].appendChild(domscript);
},
//document.write 方法写入动态脚本标签实现加载,支持跨域,在IE中支持并行下载,支持有序
loadScriptDocWrite : function(url, onload) {
document.write('<scr' + 'ipt src="' + url + '" type="text/javascript"></scr' + 'ipt>');
if (onload) {
$_E.addHandler(window, 'load', onload);
}
},
//请求下载队列
queuedScripts : [],
//XHR脚本注入法,实现并行下载,不能跨域,实现有序
loadScriptXhrInjection : function(url, onload, bOrder) {
var E = $_E;
var Q = e.queuedScripts;
var L = Q.length;
//如果是有序,加入队列
if (bOrder) {
var qScript = {response: null, onload : onload, done: false};
Q[L] = qScript;
}
var xhrObj = E.getXHRObject();
xhrObj.onreadystatechange = function() {
if (xhrObj.readyState == 4) {
if ( bOrder ) {
//有序的时候,记录请求的内容,并且等待前面的资源
Q[iQ].response = xhrObj.responseText;
E.injectScripts();
} else {
var script = document.createElement("script");
script.type = "text/javscript";
script.text = xhrObj.responseText;
document.getElementsByTagName("head")[0].appendChild(script);
if ( onload ) {onload();}
}
}
}
xhrObj.open('GET', url, true);
xhrObj.send(null);
},
//按序脚本处理
injectScripts : function() {
var Q = $_E.queuedScripts;
var len = Q.length;
for (var i = 0; i < len; i++) {
var qScript = Q[i];
if ( ! Q.done ) {
if ( ! qScript.response ) {
//停止!需要等待响应返回
break;
} else {
var s = document.createElement("script");
script.type = "text/javscript";
script.text = xhrObj.responseText;
document.getElementsByTagName("head")[0].appendChild(script);
if (qScript.onload) {qScript.onload();}
qScript.done = true;
}
}
}
},
//获取XHR对象,采取了延迟加载机制
getXHRObj : function() {
var xhrObj = null;
try {
xhrObj = new XMLHttpRequest();
} catch(e) {
var self = arguments.callee;
if (typeof self.activeXString != "string") {
var types = ["Msxml2.XMLHTTP.6.0",
"Msxml2.XMLHTTP.3.0",
"Msxml2.XMLHTTP",
"Microsoft.XMLHTTP"];
var len = types.length;
for (var i = 0; i < len; i++) {
try {
xhrObj = new ActiveXObject(types[i]);
self.activeXString = types[i];
} catch(e) {
continue;
}
break;
}
} else {
xhrObj = new ActiveXObject(self.activeXString);
}
}
return xhrObj;
}
};
//添加事件函数
$_E.addHandler = function(el, type, handler){
if (el.addEventListener) {
el.addEventListener(type, handler, false);
} else {
el.attachEvent('on' + type, handler);
}
}
//-->
</script>
<script type="text/javascript">
<!--
$_E.loadScript("1.js", "onload") ;
//-->
</script>
<!--
$_E = {
//单个脚本加载使用的接口,不理有序和无序
loadScript : function(url, onload) {$_E.loadScriptDomElement(url, onload);},
//多个脚本下载使用的接口,有序,并且区分域
loadScripts : function(urls, onload) {
var E = $_E;
var len = urls.length;
var bDifferent = false;//判断是否脚本处于不同域的标志
//判断是否加载的脚本不同域
for (var i = 0; i < len; i++) {
if (E.differentDomain(urls[i])) {bDifferent = true;break;}
}
var loadFunc = E.loadScriptXhrInjection;//默认使用loadScriptXhrInjection方法
var userAgent = navigator.userAgent;
//不同域
if (bDifferent) {
//如果是Firefox或者Opera浏览器,则采取loadScriptDomElement方法,否则则采用loadScriptDocWrite
if ( -1 != userAgent.indexOf('Firefox') || -1 != userAgent.indexOf('Opera')) {
loadFunc = E.loadScriptDomElement;
} else {
loadFunc = E.loadScriptDocWrite;
}
}
//进行多脚本加载
for (var i = 0; i < len; i++) {
loadFunc(urls[i], ( i+1 == len ? onload : null ), true);
}
},
//判断各个脚本是否不同域
differentDomain : function(url) {
//判断是否存在协议和主机头部,存在,则检测是否不同域,否则直接返回同域
if (0 == url.indexOf('http://') || 0 == url.indexOf('https://')) {
var mainDomain = document.location.protocol + "//" + document.location.host + "/";
return (0 !== url.indexOf(mainDomain));
}
return false;
},
//动态脚本注入方式,支持并行加载,支持跨域,在Opera和Firefox中是有序下载
loadScriptDomElement : function(url, onload) {
var domscript = document.createElement("script");
domscript.type = "text/javascript";
domscript.src = url;
if (onload) {
domscript.onloadDone = false;
domscript.onload = onload;
domscript.onreadystatechange = function(){
if (("loaded" == domscript.readyState || "completed" == domscript.readyState) && !domscript.onloadDone) {
domscript.onloadDone = true;
domscript.onload();
}
}
}
document.getElementsByTagName("head")[0].appendChild(domscript);
},
//document.write 方法写入动态脚本标签实现加载,支持跨域,在IE中支持并行下载,支持有序
loadScriptDocWrite : function(url, onload) {
document.write('<scr' + 'ipt src="' + url + '" type="text/javascript"></scr' + 'ipt>');
if (onload) {
$_E.addHandler(window, 'load', onload);
}
},
//请求下载队列
queuedScripts : [],
//XHR脚本注入法,实现并行下载,不能跨域,实现有序
loadScriptXhrInjection : function(url, onload, bOrder) {
var E = $_E;
var Q = e.queuedScripts;
var L = Q.length;
//如果是有序,加入队列
if (bOrder) {
var qScript = {response: null, onload : onload, done: false};
Q[L] = qScript;
}
var xhrObj = E.getXHRObject();
xhrObj.onreadystatechange = function() {
if (xhrObj.readyState == 4) {
if ( bOrder ) {
//有序的时候,记录请求的内容,并且等待前面的资源
Q[iQ].response = xhrObj.responseText;
E.injectScripts();
} else {
var script = document.createElement("script");
script.type = "text/javscript";
script.text = xhrObj.responseText;
document.getElementsByTagName("head")[0].appendChild(script);
if ( onload ) {onload();}
}
}
}
xhrObj.open('GET', url, true);
xhrObj.send(null);
},
//按序脚本处理
injectScripts : function() {
var Q = $_E.queuedScripts;
var len = Q.length;
for (var i = 0; i < len; i++) {
var qScript = Q[i];
if ( ! Q.done ) {
if ( ! qScript.response ) {
//停止!需要等待响应返回
break;
} else {
var s = document.createElement("script");
script.type = "text/javscript";
script.text = xhrObj.responseText;
document.getElementsByTagName("head")[0].appendChild(script);
if (qScript.onload) {qScript.onload();}
qScript.done = true;
}
}
}
},
//获取XHR对象,采取了延迟加载机制
getXHRObj : function() {
var xhrObj = null;
try {
xhrObj = new XMLHttpRequest();
} catch(e) {
var self = arguments.callee;
if (typeof self.activeXString != "string") {
var types = ["Msxml2.XMLHTTP.6.0",
"Msxml2.XMLHTTP.3.0",
"Msxml2.XMLHTTP",
"Microsoft.XMLHTTP"];
var len = types.length;
for (var i = 0; i < len; i++) {
try {
xhrObj = new ActiveXObject(types[i]);
self.activeXString = types[i];
} catch(e) {
continue;
}
break;
}
} else {
xhrObj = new ActiveXObject(self.activeXString);
}
}
return xhrObj;
}
};
//添加事件函数
$_E.addHandler = function(el, type, handler){
if (el.addEventListener) {
el.addEventListener(type, handler, false);
} else {
el.attachEvent('on' + type, handler);
}
}
//-->
</script>
<script type="text/javascript">
<!--
$_E.loadScript("1.js", "onload") ;
//-->
</script>