首页 > 其他 > 详细

模块加载框架 详解

时间:2014-03-04 16:06:05      阅读:745      评论:0      收藏:0      [点我收藏+]

直接贴代码,马上下班了,有时间再整理讲解一下

bubuko.com,布布扣
  1 (function(win, doc){
  2     
  3     var c = {
  4         callback:{}
  5     }
  6     
  7     function isType(type){
  8         return function(obj){
  9             return Object.prototype.toString.call(obj).toLowerCase() == "[object "+type.toLowerCase()+"]";
 10         };
 11     }
 12     var isFunction = isType("function");
 13     var isObject = isType("object");
 14     var isString = isType("string");
 15     var isNumber = isType("number");
 16     var isArray = isType("array");
 17     
 18     var MODULES = {};
 19     var LOADINGS = {};
 20     var W3C = document.dispatchEvent;
 21     var DEPS_RE = /"(?:\\"|[^"])*"|‘(?:\\‘|[^‘])*‘|\/\*[\S\s]*?\*\/|\/(?:\\\/|[^\/\r\n])+\/(?=[^\/])|\/\/.*|\.\s*require|(?:^|[^$])\brequire\s*\(\s*(["‘])(.+?)\1\s*\)/g;
 22     var HEAD = doc.getElementsByTagName("head")[0];
 23     var READY_STATE_RE = /^(?:loaded|complete|undefined)$/;
 24     var method = W3C ? "onload" : "onreadystatechange";
 25       
 26     var STATUS = {
 27         INIT:1,
 28         LOADING:2,
 29         LOADED:3,
 30         COMPLATE:4
 31     };
 32     
 33     var log = function(msg){
 34         if(console){
 35             console.log(msg); 
 36         }else{
 37             alert(msg);
 38         }
 39     }
 40       
 41     function getModPath(name){
 42         if(!PATHS[name]){
 43             //console.log(name+" is undefined")
 44         }
 45         return name && PATHS[name];
 46     }
 47       
 48     var inArray = function(child, array){
 49         var i=0,len = array.length;
 50         for(;i<len;i++){
 51             if(child == array[i]){
 52                 return true;
 53             }
 54         }
 55         return false;
 56     };
 57       
 58     function checkIsDone(deps){
 59         var i=0,len = deps.length,done = true;
 60         for(;i<len;i++){
 61             if(!MODULES[deps[i]]){
 62                 done = false;
 63             }
 64         }
 65         return done;
 66     }
 67     
 68     
 69     //检查循环依赖
 70     function checkCycle(mod, deps){
 71         
 72         var  parent, bln = false;
 73         if(!deps.length){
 74             return bln;
 75         }
 76         
 77         parent = mod.parent;
 78         for(var j=0;j<parent.length;j++){
 79             for(var i =0,len=deps.length;i<len;i++){
 80                 if(parent[j].name == deps[i] ){
 81                   return bln=true;
 82                   }
 83             }
 84             if(bln){
 85               return bln;  
 86             }else{
 87                 bln = checkCycle(parent[j],deps);
 88             }
 89         }
 90         
 91         
 92         return bln;
 93     }
 94  
 95     function addCallback(name, fn){
 96         var aCall = c.callback[name];
 97         if(aCall) {
 98             aCall.push(fn)
 99         }else{
100             c.callback[name] = [fn];
101         }
102     }
103      
104     function fireCallback(name){
105         if(c.callback[name]){
106             var i=0, aCall =c.callback[name],len=c.callback[name].length, mod = MODULES[name]; 
107             if(aCall && len && mod) {
108                 for(;i<len;i++){
109                     aCall[i](mod.exec());
110                 }
111             }
112         }
113     }
114      
115     function hasCallback(name){
116         if(c.callback[name] && c.callback[name].length){
117             return true;
118         }
119         return false;
120     }
121  
122     function loadJS(path){
123         if(!path){
124             return false;
125         }
126         var script = doc.createElement("script");
127         script.src = path;
128         HEAD.insertBefore(script,HEAD.firstChild);
129         
130         script[method] = function(e){
131             if (READY_STATE_RE.test(script.readyState)) {
132               script.onload = script.onerror = script.onreadystatechange = null;
133               HEAD.removeChild(script);
134               script = null;
135             }
136         };
137         
138         return script;
139     }
140     function use(name, callback){
141         var m = MODULES[name];
142             if(!m){
143                 m = (MODULES[name] = new Loadmod(name));
144                 m.isLoadDeps = true;
145                 addCallback(name, callback);
146                 m.load();
147             }else{
148                 addCallback(name, callback);
149                 m.checkDeps();
150             }
151             
152     }
153     function parseDependencies(code) {
154       var ret = [];
155       code.replace(DEPS_RE, function(m, m1, m2) {
156             if (m2) {
157               ret.push(m2);
158             }
159           });
160       return ret;
161     }
162     function Loadmod(name){
163         this.name = name;
164         this.status = STATUS.INIT;
165         this.deps = [];
166         this.isLoadDeps = false;
167         this.exports = {};
168         this._nw = 0;
169         this.parent = [];
170     }
171     Loadmod.prototype = {
172         
173         load:function(){
174 
175             if(this.status == STATUS.INIT){
176                 
177                 loadJS(getModPath(this.name));
178                 this.status = STATUS.LOADING;
179             }
180             
181         },
182         onload:function(){
183             this.status = STATUS.LOADED;
184             if(this.isLoadDeps){
185                 this.checkDeps();
186             }
187         },
188         setnw:function(){
189             if(this._nw ==0) return;
190             if((--this._nw) == 0){
191                 this.complate();
192             }
193         },
194         setDeps:function(deps){
195             this.deps = deps;
196             this._nw = deps.length;
197         },
198         checkDeps:function(){
199             if(this.factory){
200                  var deps = parseDependencies(this.factory.toString());
201                  if(deps.length){
202                     this.setDeps(deps);
203                     this.loadDeps();
204                  }else{
205                      this.complate();
206                  }
207             }else{
208                 this.load();
209             }
210         },
211         loadDeps:function(){
212             var self = this;
213             if(this.deps.length){
214                 for(var i=0;i<this.deps.length;i++){
215                      var m = MODULES[this.deps[i]];
216                      if(m){
217                              m.setParent(this);
218                             if(m.status == STATUS.COMPLATE){                    
219                                 this.setnw();  
220                             }else{
221                                 m.checkDeps();
222                             }
223                       }else{
224                           m = (MODULES[this.deps[i]] = new Loadmod(this.deps[i]));
225                           m.isLoadDeps = true;
226                           m.setParent(this);
227                           m.load();
228                       }
229                 }
230             }else{
231                 this.complate();
232             }
233         },
234         setParent:function(parent){
235             this.parent.push(parent);
236         },
237         getDeps:function(){
238             return this.deps.length ? this.deps : parseDependencies(this.factory.toString());
239         },
240         complate:function(){
241             this.status = STATUS.COMPLATE;
242             this.updateParent();
243             this.doCallback();
244         },
245         updateParent:function(){
246             if(this.parent.length){
247                 var i=0,len = this.parent.length;
248                 if(this.parent[i].status!= STATUS.COMPLATE){
249                     for(;i<len;i++){
250                         this.parent[i].setnw();
251                     }
252                 }
253             }
254         },
255         exec:function(){
256             
257             if(!this.cache){
258                 var exports = {}, module = this;
259                 exports = this.factory(require,module.exports = {} ,module) || module.exports;
260                 module.cache = exports;
261             }
262             return this.cache;
263         },
264         doCallback:function(){
265             fireCallback(this.name);
266         }
267     };
268 
269     function require(name){
270         
271         return MODULES[name].exec();
272     }
273  
274     function define(name, fn){
275         if(!isString(name)){
276             return false;
277         }
278         var m = MODULES[name] || (MODULES[name] = new Loadmod(name));
279             m.factory = fn;
280             var time = new Date().getTime();
281             if(checkCycle(m, m.getDeps())){
282                 log(name+" 存在循环依赖关系");
283                 return;
284             }
285             console.log(m.name+"|"+(new Date().getTime()-time));
286             m.onload();
287     }
288     
289     define.cmd = {};
290     win.useJs = use;
291     win.define = define;
292     
293 })(window, document)
bubuko.com,布布扣

模块加载框架 详解,布布扣,bubuko.com

模块加载框架 详解

原文:http://www.cnblogs.com/yyqhlw/p/3579294.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!