天天看點

《JavaScript架構設計》——2.3 require方法

本節書摘來自異步社群《javascript架構設計》一書中的第2章,第2.3節,作者:司徒正美著,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視

require方法的作用是當依賴清單都加載完畢,執行使用者回調。是以這裡有個加載的過程,整個加載過程分為以下幾步。

(1)取得依賴清單的第一個id,轉換為url。無論是通過basepath+id+".js",還是以映射的方式直接得到。

(2)檢測此子產品有沒有加載過,或正在被加載。是以我們需要一個對象來保持所有子產品的加載情況。當使用者從來沒有加載過此節點時,就進入加載流程。

(3)建立script節點,綁定onerror、onload、onreadychange等事件判定加載成功與否,然後添加href并插入dom樹,開始加載。

(4)将子產品的url,依賴清單等建構成一個對象,放到檢測隊列中,在上面的事件觸發時進行檢測。

在mass的加載器,它支援允許第一個參數為字元串,然後内部按空格或逗号切分為id數組,以及做去重處理,其他都一樣。

mass在這基礎上做了擴充。

(1)子產品id本來就是url的簡體,是以可以包含斜線(/),并以/劃分為多項。

(2)子產品id應該是以符合變量的規則的字元串組成,第一個項可以是“.”或“..”。這些都是url的基本的規則,表示目前目錄與父目錄。

(3)子產品id的未尾可以包含“.js”,但如果它是指向一個css檔案,那麼必須以css結尾。

(4)如果以“/”或“./”開頭,表示它與加載它的子產品在同一目錄。

(5)如果以“..”開頭,表示它在加載它的子產品的上一級目錄,如果存在多個“..”,就要向上找。

(6)如果子產品id是“mass”,不做轉換與加載,這表示mass架構的種子子產品,也就是加載器的所在子產品。

(7)如果子產品id是“ready”,不做轉換與加載,這用于延遲使用者回調到dom樹建完後執行。避免出現domready的回調函數與子產品的回調函數出現套嵌。

(8)如果情況就直接在前面按上basepath——加載器所在的目錄!

除了這些情況外,我們通常還用到映射,就是允許使用者在事前用一個方法,把id與完整的url對應好,這樣就直接拿。mass稱之為别名機制。id隻是給使用者用的,架構還是url做加載或其他檢測。此外,amd還發展一種shim技術,shim就是墊片的意思,目的是讓不符合amd定義的javascript檔案也能無縫切入我們的加載器系統。

如這個是普通的别名機制:

而對于jquery或其插件,我們需要shim機制:

下面是require的源碼:

每require一次,相當于把目前的使用者回調當成一個不用加載的匿名子產品,id是随機生成,回調是否執行,要待到deps對象裡面所有值都為2。

require裡有三個重要方法:loadjscss,它用于轉換id為url,後面再調用loadjs, loadcss,或再調用require方法;firefactory,就是執行使用者回調,我們的最終目的;checkdeps,檢測依賴是否都安裝好,安裝好就執行firefactory。

注意,上面的modules[src]是以完整路徑做id的,它對應的對象沒有state屬性,表示其正在加載中。

loadjs與loadcss方法就比較純粹了,不過loadjs會做個死鍊檢測checkfail。

checkfail方法主要是用于開發調試。有3個參數。node——script節點,onerror——是否為onerror觸發,fuckie——對應舊版本ie的hack。思路是,javascript檔案從加載到解析到執行需要一個過程,在interact階段,我們的javascript代碼已經有些部分可以執行了,這時我們将子產品對象的state改為1,如果還是undefined,我們就可識别它為死鍊。不過,此hack對不是以amd定義的javascript子產品無效,因為将state改1的邏輯是由define方法執行的。如果判定是死鍊,我們就把此節點移除。

checkdeps方法會在使用者加載子產品之前及script.onload後各執行一次,檢測子產品的依賴情況,如果子產品沒有任何依賴或state都為2了,我們調用firefactory方法。

曆經千辛萬苦,我們終于到達firefactory方法。它的工作是從modules中收集各子產品的傳回值,執行factory, 完成子產品的安裝。

繼續閱讀