说我有三个模块和一个主要模块:
//Module A
define([''], function(){
function initialize(param1, param2){
//initialize stuff
}
//other stuff
return {
initialize: initialize,
//whatever else
};
});
//Module B
define(['ModuleA'], function(ModuleA){
function initialize(param2, param3){
//initialize stuff using ModuleA
}
//other stuff
return {
initialize: initialize,
//whatever else
};
});
//Module C
define(['ModuleB'], function(ModuleB){
function initialize(param4, param5){
//initialize stuff using ModuleB
}
//other stuff
return {
initialize: initialize,
//whatever else
};
});
//main module
require(['ModuleA', 'ModuleB', 'ModuleC'], function(ModuleA, ModuleB, ModuleC){
ModuleA.initialize(arg1, arg2);
ModuleB.initialize(arg3, arg4);
ModuleC.initialize(arg5, arg6);
});
这里的问题是主模块中所有初始化调用之间都有时间耦合。作为程序员,我必须在必须初始化模块的哪个顺序中记住。如果模块在模块之前初始化,则基本上将使用非初始化的模块,因为尚未初始化Modulea。现在,我可以使用依赖项注入,其中我实际上通过模块和通过初始化方法的参数模拟了他们的依赖项,但这将失败requirejs的目的,即要处理依赖关系。我最好只使用脚本标签并手动通过依赖项,确保每个脚本都是独立的。我很想知道是否还有其他解决方案。谢谢!
您可以在定义函数中进行模块初始化并在define([..]
中指定其依赖关系是什么:
//Module A
define(['SomeModule'], function(SomeModule){
// initialization of the module
return {
//initializedModuleInterface..
};
});
如果您在模块之间绊倒了循环依赖关系,而不是从模块返回的接口中,请删除第二个模块的需求,直到使用模块提供的功能,例如,不需要它。define([..]
但是当模块本身使用时: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
如何使用requirjs/amd处理循环依赖关系?
初始化参数本身可能是提供配置参数的另一个模块。
编辑1:添加requirejs作为动态模块定义器和加载程序
如果需要动态依赖注入机制的结构,则您仍然可以使用requirej。不知道它是否是为此设计的:
1。当您手头有必要的配置var时,请执行动态模块通过requirejs
定义for ex:
angular.module('myModule')
.run(function () {
define('myConf', [], function() {
return {
confA: 1,
confB: 2
};
});
});
2。在依赖myConf
模块的模块中,照常进行:
// Module: ModuleA
define(['myConf', function(myConf) {
// initialization with myConf values.
console.log(myConf.confA);
return some_interface;
});
或
define(function(require) {
var myConf = require('myConf');
console.log(myConf.confA);
// initialization with myConf values.
return some_interface;
});
3。在应用程序的生命周期中,当需要ModuleA
,ModuleB
..然后需要:
var moduleReq = 'moduleA';
require([moduleReq], function (moduleA) {
// doSomething with moduleA
});
这里的诀窍是通过define('myConf', [], function() {..})
具有特定名称的模块的动态定义。它使您可以在不需要文件的情况下定义一个模块,并且可以在应用程序的寿命中动态动态。据我了解,它主要用于Requirejs捆绑解决方案。
编辑2:第二种方法 - 使用" requirejs"模块内的承诺作为内部依赖关系管理。
可以使用的另一种方法是在requirejs模块内使用承诺来指定依赖项等待。
我们可以将模块主构造定义为承诺,并在拥有必要的数据时通过接口Init函数解决它。
1。我们像往常一样将每个模块指定为系统中的文件。 2。在confModule
中,我们要动态初始化,我们以这种模式构建它:
// 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);
}
}
});
我们解决了构造函数之外的承诺。附加链接提供了有关该模式的好处和陷阱的更多信息。
3。在依赖模块中,我们以相同的模式定义它们,而无需INIT功能,并添加等待构图的承诺:
// 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。在我们的代码中,当我们拥有所需的数据时,我们可以使构造量化:
define(['confModule', function (confModule) {
// some async get of confData
$.get(url, function (data) {
confModule.init(data.a, data.b);
});
});
5。在使用Modulea时的代码中,我们需要将其用作承诺:
define(['moduleA'], fucntion (moduleA) {
moduleA.then(function (moduleAInteface) {
// do something with moduleA.
});
});