使用RequireJS进行依赖注入
Dependency Injection with RequireJS
我可以拉伸多少RequireJS为我的应用程序提供依赖注入?举个例子,假设我有一个模型,我希望它是单例的。不是自我强制的getInstance()类型的单例,而是上下文强制的单例(每个"上下文"一个实例)。我想做一些事情,比如……
require(['mymodel'], function(mymodel) {
...
}
让mymodel成为mymodel类的一个实例。如果我要在多个模块中这样做,我希望我的模型是相同的,共享的实例。
我已经成功地使mymodel模块这样工作:
define(function() {
var MyModel = function() {
this.value = 10;
}
return new MyModel();
});
这种类型的使用是预期的和常见的,还是我滥用了RequireJS?是否有更合适的方式,我可以执行依赖注入与RequireJS?谢谢你的帮助。
这实际上不是依赖注入,而是服务位置:您的其他模块通过字符串"key "请求"类",并返回"服务定位器"(在本例中为RequireJS)已连接为它们提供的"类"的实例。
依赖注入包括返回MyModel
构造函数,即return MyModel
,然后在中央组合根中将MyModel
的实例注入到其他实例中。我在这里整理了一个如何工作的示例:https://gist.github.com/1274607 (也在下面引用)
这样,组合根决定是否分发MyModel
的单个实例(即使其单例作用域)或每个需要它的类的新实例(实例作用域),或介于两者之间。这个逻辑既不属于MyModel的定义,也不属于请求它的实例的类。
(旁注:虽然我没有使用它,但wire.js是一个成熟的JavaScript依赖注入容器,看起来很酷。)
你这样使用RequireJS并不一定是在滥用它,尽管你所做的看起来有点迂回,比如声明一个类而不是返回它的一个新实例。为什么不这样做呢?
define(function () {
var value = 10;
return {
doStuff: function () {
alert(value);
}
};
});
您可能错过的类比是,模块相当于大多数其他语言中的"名称空间",尽管您可以将函数和值附加到名称空间上。(所以更像Python,而不是Java或c#。)它们并不等同于类,尽管正如您所展示的,您可以使模块的导出等于给定类实例的导出。
所以你可以通过将函数和值直接附加到模块来创建单例,但这有点像通过使用静态类创建单例:它是高度不灵活的,通常不是最佳实践。然而,大多数人确实把他们的模块当作"静态类",因为正确地为依赖注入构建一个系统需要从一开始就进行大量的思考,这在JavaScript中并不是真正的规范。
这里是https://gist.github.com/1274607 inline:
// EntryPoint.js
define(function () {
return function EntryPoint(model1, model2) {
// stuff
};
});
// Model1.js
define(function () {
return function Model1() {
// stuff
};
});
// Model2.js
define(function () {
return function Model2(helper) {
// stuff
};
});
// Helper.js
define(function () {
return function Helper() {
// stuff
};
});
// composition root, probably your main module
define(function (require) {
var EntryPoint = require("./EntryPoint");
var Model1 = require("./Model1");
var Model2 = require("./Model2");
var Helper = require("./Helper");
var entryPoint = new EntryPoint(new Model1(), new Model2(new Helper()));
entryPoint.start();
});
如果您认真对待DI/IOC,您可能会对wire.js: https://github.com/cujojs/wire
感兴趣。我们使用了服务重定位(像Domenic描述一样,但是使用curl.js而不是RequireJS)和DI(使用wire.js)的组合。在测试控制中使用模拟对象时,服务重定位非常方便。DI似乎是大多数其他用例的最佳选择。
在自我强制的getInstance()类型的单例中不是单例,而是上下文强制的单例(每个"上下文"一个实例)。
我建议它只用于静态对象。在require/define块中加载一个静态对象作为模块是完全可以的。然后创建一个只有静态属性和函数的类。然后你就有了相当于Math Object的对象,它有像PI、E、SQRT这样的常量和round()、random()、max()、min()这样的函数。非常适合创建可以随时注入的Utility类。
而不是:
define(function() {
var MyModel = function() {
this.value = 10;
}
return new MyModel();
});
创建一个实例,使用静态对象的模式(其中的值总是相同的对象永远不会被实例化):
define(function() {
return {
value: 10
};
});
或
define(function() {
var CONSTANT = 10;
return {
value: CONSTANT
};
});
如果你想传递一个实例(使用一个返回new MyModel();的模块的结果),那么,在初始化函数中,传递一个捕获当前状态/上下文的变量,或者传递一个包含模块需要知道的状态/上下文信息的对象。
- AngularJS依赖注入定时问题
- JavaScript模块化和依赖注入之间的区别
- 编写Karma+Mocha测试,同时使用依赖注入和“完成”
- Angular2文档-层次依赖注入程序(恢复服务)
- 使用依赖注入在 JavaScript 中返回函数
- 如何从指令的控制器调用依赖注入服务的嵌套方法
- AngularJS'依赖注入和RequireJS本质上是相同的
- 为Backbone.js应用程序设计依赖注入系统的范围界定问题
- 当使用Angular1+ES6时,控制器函数中未定义依赖注入,控制器是一个类
- 角度依赖注入,使用服务在模块之间传递值
- 如何使用JS(浏览器端)中的“require”和依赖注入,服务位置
- Angular ui-router 解析中的动态依赖注入
- Angularjs |依赖注入优于需要模块的优势
- AngularJS 依赖注入在哪里指定
- 如何在 Nodejs 中进行有效的依赖注入
- 无法解决条带角依赖注入
- Undefined不是函数和依赖注入
- Angular 指令是否需要将依赖注入到控制器中
- AngularJS中的依赖注入仅适用于Angular“对象”吗?
- 角度依赖注入,如果将控制器、服务等分离到单独的模块中