You can do the module initialization in the define function and specify in the define([..]
what are its dependencies:
//Module A
define(['SomeModule'], function(SomeModule){
// initialization of the module
return {
//initializedModuleInterface..
};
});
If you are stumbling upon circular dependencies between your modules, than you can in the interface you return from a module, deffer the need of the second module up until the usage of the module provided function for instance, by requiring it not in the define([..]
but when the module itself get used: require("a").doSomething();
//Inside b.js:
define(["require", "a"],
function(require, a) {
//"a" in this case will be null if "a" also asked for "b",
//a circular dependency.
return function(title) {
return require("a").doSomething();
}
}
);
http://requirejs.org/docs/api.html#circular
How to handle circular dependencies with RequireJS/AMD?
The initialization params themselves could be another module providing configuration params.
Edit 1: Add usage of requirejs as dynamic module definer and loader
If the need is for a structure of dynamic dependency injection mechanism, you still can use requirejs for that. Not sure if it was designed for it though:
1 . When you have the necessary config var in hand, then do a dynamic module define via requirejs
For ex:
angular.module('myModule')
.run(function () {
define('myConf', [], function() {
return {
confA: 1,
confB: 2
};
});
});
2 . In the modules that relies on the myConf
module do as usual:
// Module: ModuleA
define(['myConf', function(myConf) {
// initialization with myConf values.
console.log(myConf.confA);
return some_interface;
});
or
define(function(require) {
var myConf = require('myConf');
console.log(myConf.confA);
// initialization with myConf values.
return some_interface;
});
3 . In the lifecycle of the app, when ModuleA
, ModuleB
.. is needed then:
var moduleReq = 'moduleA';
require([moduleReq], function (moduleA) {
// doSomething with moduleA
});
The trick here is the dynamic defining of a module with a specific name via define('myConf', [], function() {..})
. It lets you define a module without the need of a file and dynamically anytime in the lifespan of the application. From what I understand it mainly used for requirejs bundling solutions.
Edit 2: Second approach - Using promises inside requirejs modules as inner dependency management.
Another approach that can be used is to use Promise inside requirejs modules to specify dependencies to wait on.
We can define a module main construct as a promise and resolve it via an interface init function when we have the necessary data.
1 . We specify every module as a file in the system as usual.
2 . In the confModule
we want to be dynamically initialize, we build it in this pattern:
// confModule
define([], function () {
var resolveMain;
var rejectMain;
var promise = new Promise(resolve, reject) {
resolveMain = resolve;
rejectMain = reject;
}
return {
init: function (confVarA, confVarB) {
try {
var moduleInitialized = {
// some preparation of confModule
confVarA: confVarA,
confVarB: confVarB
};
resolve(moduleInitialized);
}
catch (e) {
rejectMain(e);
}
},
then: function (successFn, errorFn) {
return promise.then(successFn, errorFn);
}
}
});
We resolve the promise outside of the constructor. Attach linked provides more info on the benefits and pitfalls of that pattern.
3 . In the dependent modules, we define them in the same pattern without needed the init functionality, and adding waiting on the promise of the confModule:
// moduleA
define(['confModule'], function (confModule) {
var resolveMain;
var rejectMain;
var promise = confModule.then(function(confModuleData) {
var moduleBInterface = {
// prepare module b
};
return moduleBInterface; // this make the promise return another promise to wait on for moduleBInterface return;
};
return {
then: function (successFn, errorFn) {
return promise.then(successFn, errorFn);
}
}
});
4 . In our code, we can initalize confModule when we have the data we need:
define(['confModule', function (confModule) {
// some async get of confData
$.get(url, function (data) {
confModule.init(data.a, data.b);
});
});
5. In our code when using moduleA, we need to use it as a promise:
define(['moduleA'], fucntion (moduleA) {
moduleA.then(function (moduleAInteface) {
// do something with moduleA.
});
});