Ruby's Louvre

每天学习一点点算法

导航

我的模块加载系统 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)

https://github.com/BorisMoore/DeferJS https://bitbucket.org/scott_koon/bootstrap/src/a94d219da3e9/README http://jupiterjs.com/news/stealjs-script-manager http://bdframework.org/bdLoad/ https://github.com/unscriptable/curl http://www.dustindiaz.com/scriptjs/ https://github.com/rgrove/lazyload/ https://github.com/Cerdic/jQl http://yepnopejs.com/ http://labjs.com/ http://headjs.com/ http://stevesouders.com/controljs/ http://requirejs.org/ https://github.com/chriso/load.js http://www.andresvidal.com/jsl

posted on 2011-03-01 22:08  司徒正美  阅读(3192)  评论(6编辑  收藏  举报