module.js是整个seajs最核心的部分,包含主要api的实现。咱们先简化下这段的结构以下:api
//模块构建类 function Module(uri, deps) { } //模块对象的实例函数,用于解析依赖 Module.prototype.resolve = function(){ //内部调用工具方法获取依赖 var uris = Module.resolve() return uris; } //加载依赖 Module.prototype.load = function(){ //获取全部依赖 mod = this; var uris = mod.reslove();//返回依赖数组 //循环加载依赖 for(){ Module.get //获取这个依赖 m.fetch()//加载这个依赖 m.load()//加载依赖的依赖 } //最后触发模块的onload mod.onload() } //加载完毕后回调 Module.prototype.onload = function(){ //触发callback mod.callback() } //真正获取模块 Module.prototype.fetch = function(){} //执行模块 Module.prototype.exec = function(){ //获取factory var factory = mod.factory; //执行时传入三个参数require、exports、module factory(require, mod.exports = {}, mod) //返回值 return exports } //工具方法 //id转为绝对url函数 Module.resolve = function(){ //实际上调用的是seajs.resolve seajs.resolve() } //申明模块 Module.define = function(){ //获取代码内的require依赖 if (!isArray(deps) && isFunction(factory)) { deps = parseDependencies(factory.toString()) } //内部调用Module.save保存模块 Module.save() } //保存模块 Module.save = function(){ //获取模块,保存初始化信息 var mod = Module.get(uri) mod.id = ... mod.dependencies = ... mod.factory = ... } //获取模块 Module.get = function(){ //从缓存获取,若是没有就建立 } //use一个模块 Module.use = function(){ //获取该模块 var mod = Module.get(); //绑定回调 mod.callback = function(){} //加载依赖 mod.load() } //预加载模块 Module.preload = function(){ //调用use加载预加载模块 Module.use(); } //暴露api global.define = Module.define seajs.use = function(){} seajs.require = function(){}//没有做为对外api使用,可是能够这么用
接下来经过看两个api的执行过程,了解上述全部函数,一个是seajs.use(),一个是define()数组
seajs.use(url,function(){});调用过程:缓存
1.先调用Module.preload加载最早应当加载的依赖,就是前文所说的带在url上的那种。preload的内部仍是会调用第二步中的Module.use函数
2.调用Moduel.use;这里作了三件事工具
1).调用Module.get生成模块对象mod,并附上惟一idfetch
2).为模块绑定好callback,为加载完以后调用(这里的callback不只把seajs.use传入的callback放进去执行,还把全部的依赖模块执行后的结果传入到callback参数中)ui
3).调用mod.load()实例方法开始加载依赖。this
3.进入mod.load()加载依赖,具体以下:url
1).调用实例方法mod.resolve获取全部依赖数组。spa
mod.resolve的过程又以下:
a.调用工具函数Module.resolve
b.工具函数Module.resolve内部调用seajs.resolve
c.seajs.resolve=id2url
d.上文util-path.js中id2url内部调用了parseAlias各类转换函数获得依赖的绝对路径。
2).为每一个依赖生成模块对象
3).全部依赖都加载完毕时,执行mod.onload()
onload内部执行2的2)中已经为该模块绑定好的callback
4).依赖未所有加载完,执行mod.fetch()
fetch()的内部实际使用的是seajs.request(),可是这里只是进行了循环绑定,还未执行,就是上文util-request.js中动态插入js标签的方法。
5).所有循环执行过fetch后,最后统一再次循环执行插入js的操做。
define('路径',function(){}),define挂载在global(也就是window)下,因此咱们引入seajs后能够直接使用define(),他的执行过程以下:
1.global.define = Module.define
2.Module.define内部只作了一件事,调用Module.save存储该模块相关信息。
3.Module.save从简化结构能够看出他的做用是给生成的模块对象实例写入一些有用的信息,供以后使用。
以上基本是use和define两个api的执行过程和调用函数链,基本覆盖了代码结构中的全部函数调用,须要特殊指出的是Module.prototype.exec模块对象执行函数。
Module.prototype.exec函数只是在模块绑定callback回调时用到,为模块加载依赖时,首先每一个依赖都会生成Module实例,须要让每一个依赖实例调用执行方法,咱们才能拿到这些依赖的返回值。