一:
1.本文是基於seajs2.2.1編寫的,之后版本應該大同小異
2.本文僅代表個人觀點,如有理解錯誤,敬請指出,大家一起學習
二:
1.首先放一張我畫的流程圖
這是我理解的seajs的基本的所有流程,接下來通過代碼結合該流程圖講解下我的理解
2.1.首先從seajs.use開始,如以下圖的代碼所示
首先執行preload方法,看preload方法,其實就是執行module.use方法,所以我們直接從module.use講起,先獲取module,如果沒有就新建,並且緩存在cachedMods中,定義callback方法(之后會講),然后執行module.load方法(注意module.get方法,是把所有的ids當做deps傳入的)
2.2.module.load方法
看代碼,第一次進來,該模塊的status還是0,第一個if判斷主要是為了require同一個模塊多次時只需加載一次(已經loading的只需等他自己的回調),然后resolve方法是用來解析路徑的,emit該方法是用來觸發seajs自己定義的事件的,seajs.on可以定義事件,這里會觸發load事件(如果有自定義),之后的for循環是若主模塊的依賴模塊還沒被加載,就在被依賴的模塊的waiting數組中放入主模塊的key值以及被依賴次數。當主模塊的remain為0時,就加載自身代碼,否則往下進入Module.prototype.fetch方法
2.3.Module.prototype.fetch
首先改變狀態為fetch,fetchinglist和callbackList分別用來判斷和緩存模塊,把sendrequest方法存入requestCache返回回去(在sendrequest中有吧onrequest方法傳了進去(待會會調用到)),然后module.load方法繼續執行,看2.2的圖最后一個for循環遍歷所有依賴模塊執行sendrequest.
module.status更新為FETCHING.
2.4.sendRequest(seajs.request) 以及addonload
執行request方法,創建一個節點,在該節點上加上一個onload方法,然后插入該節點,插入后會執行插入的代碼,一般我們是這么寫seajs的,如下
sea.use('a',function(){}); define(function(require,exports,module){var b require('b'); ...;})
所以插入會執行define的方法,define方法主要作用是更新deps和factory,他會根據正則匹配把所有require里面的內容提出來,找到絕對路徑,再把factory緩存下來,便於之后執行。
(這里舉個例子,如上面的代碼,主模塊a一開始的deps為他自身a,當a模塊load進來,執行define函數,a的deps就更新為b了)
然后就執行addonload中的callback方法
2.5.onRequest--> module.load
見2.3的圖,主要的作用是讓他的子模塊執行module.load方法,如果子模塊也有依賴,則重復上述步驟,如果沒有,則會進入Module.prototype.onload方法
module.status更新為SAVED-->module.status更新為LOADING
2.6.Module.prototype.onload
mod.callback是當只有使用seajs.use時定義的,可以認為只有主模塊會執行,for循環寫的是當被依賴的模塊加載一次,主模塊的remain就減去相應的數量,直至為0,主模塊進入onload方法,由於主模塊youcallback,執行mod.callback()
module.status更新為LOADED
2.7mod.callback()-->module.prototype.exec(部分見圖2.1)
圖2.1的圖中可以看出,模塊會先執行module.prototype.exec后會執行自定義的callback方法。
module.prototype.exec就是執行factory方法,也就是define時定義的方法,這里有幾個方法,require方法主要作用是執行引進來的方法(已經在前面把他加載進來了,但是還未執行,執行factory時順序執行require方法,被返回exports)
require.async異步加載,其本質就是module.use就是在執行時新建了一個模塊(重走了上述步驟)
exports就是暴露出來的方法,到這里mod.status就變成status.executed了,到這里所有的就都結束了。
module.status更新為EXECUTING-->module.status更新為EXECUTED.
3.結語
有一些里面的方法及細節沒有講到,主要講了大致流程,如果有錯誤,請幫忙指出及修改,謝謝!