seajs源碼理解(二)

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實例,須要讓每一個依賴實例調用執行方法,咱們才能拿到這些依賴的返回值。

相關文章
相關標籤/搜索