RequireJS:模块嵌套需求中的动态依赖关系

时间:2014-10-15 11:11:27

标签: javascript requirejs

假设有一个函数返回包含动态依赖关系的数组。 然后在模块B中使用这些依赖关系。另一个模块A又使用模块B.

A.js

define([B], function(moduleB){
    moduleB.m();
})

B.js:

define([ dep1, dep2 ], function( dep1, dep2 ) {

    var dyndeps = dep2.getDynDeps();
    var moduleB = {}

    require(dyndeps, function() {
        moduleB.m = function() { ... };
    })

    return moduleB;

});

这种方法的问题是,内部需求是异步执行的,因此方法m不能及时获得。

1 个答案:

答案 0 :(得分:9)

由于B.m由动态依赖项提供,B应该提供一个等待它可用的接口。有许多plugins允许这样做,例如 rq (使用Q承诺), promise (使用jquery,Q,RSVP或ES6承诺), promiseme (自包含?)。

使用其中一个,B不会返回moduleB,而是一个承诺。嵌套的require调用将使用完整的moduleB解析承诺。 A需要<PLUGIN>!B。例如。使用promisejquery

// A.js
define(["promise!B"], function(moduleB){
    // B is complete now
    moduleB.m();
})

// B.js
define([ "dep1", "dep2", "jquery" ], function( dep1, dep2, $ ) {

    var dyndeps = dep2.getDynDeps();
    var moduleB = {};
    var loaded = new $.Deferred();

    require(dyndeps, function() {
        moduleB.m = function() { ... };
        loaded.resolve(moduleB);
    })

    return loaded.promise();    
});

此方法唯一存在的问题是客户端代码(A.js)需要知道以特殊方式依赖B。更好的解决方案是让B隐藏其动态特性,如:

// A.js
define(["B"], function(moduleB){
    moduleB.m();
})

// B.js
define([ "promise!dynamicB" ], function( moduleB ) {
    return moduleB;
});

// still inside B.js define a "private" named module:
define("dynamicB", ["dep1", "dep2", "jquery"], function() {
    var dyndeps = dep2.getDynDeps();
    var loaded = new $.Deferred();
    var moduleB = {};

    require(dyndeps, function() {
        moduleB.m = function() { ... };
        loaded.resolve(moduleB);
    })

    return loaded.promise();    
});

现在B可以像任何其他模块一样使用。