Suppose there is a function that returns an array containing dynamic dependencies. Then within a module B these dependencies are used. Another module A in turn uses module 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;
});
The problem with this approach is, that the inner require is executed asynchronously, so the method m is not available in time.
Since B.m is provided by a dynamic dependency, B should provide an interface for waiting on it to become available. There are a number of plugins to allow that, e.g. rq (using Q promises), promise (using jquery, Q, RSVP or ES6 promises), promiseme (self-contained?). 
Using one of those, B would not return moduleB, but a promise. The nested require call would resolve the promise with complete moduleB. A would require <PLUGIN>!B. E.g. using promise and jquery:
// 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();    
});
The only remaining problem with this approach is that the client code (A.js) needs to know to depend on B in a special way. A better solution would be to have B hide its dynamic nature like:
// 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();    
});
Now B can be used just as any other module.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With