關於requireJS的同步加載和異步加載


這篇隨筆主要記錄require('name')和require(['name1','name2'])在同步和異步加載使用的區別

1、require('name')同步加載模塊的形式

 

define(function(require, exports, module) {
        var a = require('a'),
            b = require('b');

        //Return the module value
        return function () {};
    }
);

 

(1)首先看上面的代碼,使用了var a = require('a')這樣的寫法,這是一種同步調用模塊的寫法(因為加載a模塊后直接返回而不必放在回調函數中使用), 說明此時在該define函數作用域里,模塊a已被加載裝配完畢,並可以通過require函數返回a模塊,注意此時require函數中使用的參數是模塊名而非數組;

 

(2)其次,該define函數是一種commonJS的簡化寫法,回調函數前並未聲明依賴關系的數組,即並define(['require','exports','module'],function(require, exports, module) {});這樣的寫法。此時require會使用

Function.prototype.toString() 對回調函數進行解析,並通過解析發現require('a')和require('b')。由於在調用回調函數之前,require會預先加載模塊的所有依賴,所以在調用回調函數前會預先裝配a模塊和b模塊,因此在調用require('a')和require('b')時,a和b模塊已經提前裝配好了;

 

(3)此外還需要注意的是,當define函數聲明依賴關系數組時,當需要在回調函數使用var a = require('a')這樣的寫法時必須要將所需的模塊a添加到依賴關系數組中,因為當define包含依賴關系數組時,require會將依賴關系數組中的依賴視為回調函數所需的所有依賴,即上面的代碼就應改為如下形式,否則會報依賴關系沒有加載的錯誤:

define(['require','exports','module','a','b'],function(require, exports, module) {
        var a = require('a');
            b = require('b');

        //Return the module value
        return function () {};
    }
);

 

(4) 由於使用require('name')的原理是將所需的依賴預先加載然后再能進行調用,所以不能再全局作用域中使用var a = require('a')這樣的寫法,這樣的寫法必須包含在define或require([...],function(){})的回調函數中;

 

(5)由於使用commonJS寫法時,require檢測依賴關系的機制是通過調用Function.prototype.toString() ,所以不能使用以下寫法,否則會報依賴關系沒有加載的錯誤:

define(function(require, exports, module) {
        var a = getRequireModule(require, 'a');
              b = getRequireModule(require, 'b');

        //Return the module value
        return function () {};
    }
);

function getRequireModule(require, moduleName) {
    return require(moduleName);  
}

 

2、 require(['name1', 'name2'])異步加載模塊的形式

(1)通過require([...])形式獲取模塊的依賴,和上面不同的是,調用require函數使用的參數是數組而非模塊名,這種調用方式是異步調用的方式,即不能使用var a = require(['a'])這樣的方式同步返回一個模塊,require(['a'])返回的是一個函數,而非a模塊向外部暴露的接口,應該在回調函數中使用模塊a,即如下的方式才是正確的:

define(['a'], function(a) {
   console.log(a); 
})

 

(2)和require('a')的另一個區別是,由於require(['a'])是一種異步依賴模塊的方法,所以在使用commonJS簡化的define寫法時,加載依賴關系時不會檢測到['a']中所包含的a模塊

 

(3)由於異步加載的關系,所以在使用時仍應注意有兩種情況:

     1、當依賴的模塊遵循AMD規范時,該模塊將會被包含在define函數中,會擁有自己的作用域和向外部暴露的接口,需要通過回調函數才能使用這些模塊向外提供的接口;

     2、當依賴的模塊不遵循AMD規范時,該模塊被加載后,由於模塊中的js代碼具有全局作用域,理論上能夠在外部而不必在回調函數中使用模塊的接口,但是由於模塊是異步加載的,在使用依賴模塊提供的接口時,在外部無法保證模塊是否已加載完畢,所以仍然應在回調函數中使用依賴模塊。

 

(4)當require調用需要使用回調函數時,正確的寫法應該是:

    require(['dependency'], function (dependency) {});

           寫成require('dependency', function (dependency) {});   是錯誤的


免責聲明!

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



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