我的模块加载系统 v4
本版本增加了如下特征:
- 对加载失败时的负向回调支持。由于opera在处理请求无效地址时发出的是致命错误,不能给onerror等捕捉,因此我的负向回调是对它没作用的(测试浏览器为opera11)。但能实现在IE下对script.onerror的模拟,这是我的加载器相对于其他加载器最大的优势,也是本版本最大的亮点。
dom.require(dependList,callback,/*optional*/errback) //依赖列表,正向回调,负向回调 - 如果请求地址无效,会立即中止定时器,防止没完没了的setTimeout。
- 添加更严密的检测防止重复请求。
API与用法见第三版:
//并行加载器 by 司徒正美 2011.3.1
;;;(function(WIN,DOM,undefined){
var
reg_module_name = /(?:^|\/)([^(\/]+)(?=\(|$)/,
reg_module_url = /\(([^)]+)\)/,
reg_readystate = /loaded|complete/i,
scripts = DOM.getElementsByTagName("script"),
bases = DOM.getElementsByTagName("base"),
_dom = WIN.dom,
dom = {
mix : function(target, source ,override) {
var i, ride = (override === void 0) || override;
for (i in source) {
if (ride || !(i in target)) {
target[i] = source[i];
}
}
return target;
},
noConflict: function( ) {//防止命名冲突,请先行引用其他库再引用本框架
WIN.dom = _dom;//这是别人的
return dom;//请赋以其一个命名空间
},
require:function(/*array or string*/dependList,callback,/*optional*/errback){
var self = arguments.callee,moduleNames = [], i = 0, hash = self.loadedModules, reg = reg_module_name ,name, url;
if(typeof dependList === "string"){
dependList = dependList.split(",")
}
while(url = dependList[i++]){
name = url.match(reg)[1];
if(!hash[name]){
callback.errback = errback || function(){}
callback.name = name;
callback.url = url;
moduleNames.push(name);
self.appendScript(callback);
}
}
this.provide(moduleNames,hash,callback)
},
define:function(name,dependList,callback){
var hash = this.require.loadedModules,
node = DOM.getElementById("__"+name+"__");
if(node){
node[name] +="_loaded"
}
this.require(dependList,function(){
callback();
hash[name] = 1
})
},
//提供模块
provide:function(array,hash,callback){
var flag = true, i = 0, args = arguments, fn = args.callee, name;
while(name = array[i++]){
if(!hash[name]){
flag = false;
break;
}
}
if(flag){
callback();
}else{
callback.timeoutID = setTimeout(function(){
fn.apply(null,args)
},32);
}
}
}
dom.mix(dom.require, {
loadedModules:{},
requestedUrl:{},
//http://www.cnblogs.com/rubylouvre/archive/2011/02/10/1950940.html
getBasePath:function(/*internal*/url,/*internal*/node){
try{
a.b.c()
}catch(e){
url = e.fileName || e.sourceURL;//针对firefox与safari
}
if(!url){
node = scripts[scripts.length - 1]
url = node.hasAttribute ? node.src : node.getAttribute('src', 4);
}
url = url.substr( 0, url.lastIndexOf('/'));
dom.require.getBasePath = function(){
return url;//缓存结果,第一次之后直接返回,再不用计算
}
return url;
},
appendScript:function(obj,/*internal*/url){
//处理dom.node(http://www.cnblogs.com/rubylouvre/dom/node.js)的情形
var _url = obj.url.match(reg_module_url), ref = bases[0] || scripts[0], name = obj.name;
url = _url && _url[1] ? _url[1] : this.getBasePath()+"/"+ obj.url + ".js"//?timestamp="+1*new Date;
if(!this.requestedUrl[url]){
this.requestedUrl[url] = 1;
var node = DOM.createElement("script");
node.charset = "utf-8";
node[name] = name;
node.id = "__"+name+"__";
node.async = true;//如果 async 属性为 true,则脚本会相对于文档的其余部分异步执行,这样脚本会可以在页面继续解析的过程中来执行。
node.onerror = function(){
clearTimeout(obj.timeoutID);
obj.errback();
dom.require.removeScript(this);
}
node.onload = node.onreadystatechange = function(){
if (-[1,] || reg_readystate.test(this.readyState) ){/*opera的script也存在readyState,但如果请求地址不存在,是不会进入onload回调的*/
if(node[name] !== name+"_loaded"){
clearTimeout(obj.timeoutID);
obj.errback();
}
dom.require.removeScript(this);
}
}
node.src = url;
//http://paulirish.com/2011/surefire-dom-element-insertion/
ref.parentNode.insertBefore(node,ref );
}
},
removeScript:function(node){//移除临时生成的节点
var parent = node.parentNode
if(parent && parent.nodeType === 1){
if (node.clearAttributes) {
node.clearAttributes();
} else {
node.onload = node.onreadystatechange = node.onerror = null;
}
parent.removeChild(node)
}
}
});
//先行取得核心模块的URL
dom.require.getBasePath();
window.dom = dom;
})(this,this.document)
机器瞎学/数据掩埋/模式混淆/人工智障/深度遗忘/神经掉线/计算机幻觉/专注单身二十五年
浙公网安备 33010602011771号