seajs原理解析


一:

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.結語

有一些里面的方法及細節沒有講到,主要講了大致流程,如果有錯誤,請幫忙指出及修改,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM