我目前使用nodejs创建一些实验项目。我已经用Spring编写了很多Java EE Web应用程序,并赞赏那里的依赖注入的简易性。
现在我很好奇:如何使用节点进行依赖注入?或者:我什至需要它吗?是否存在替代概念,因为编程风格不同?
到目前为止,我在谈论简单的事情,例如共享数据库连接对象,但是我还没有找到一个令我满意的解决方案。
我目前使用nodejs创建一些实验项目。我已经用Spring编写了很多Java EE Web应用程序,并赞赏那里的依赖注入的简易性。
现在我很好奇:如何使用节点进行依赖注入?或者:我什至需要它吗?是否存在替代概念,因为编程风格不同?
到目前为止,我在谈论简单的事情,例如共享数据库连接对象,但是我还没有找到一个令我满意的解决方案。
Node.js requires DI as much as any other platform. If you are building something big, DI will make it easier to mock the dependencies of your code and test your code thoroughly.
Your database layer modules for example, shouldn’t just get required at your business code modules because, when unit testing these business code modules, the daos will load and connect to the database.
One solution would be to pass the dependencies as module parameters:
module.exports = function (dep1, dep2) {
// private methods
return {
// public methods
test: function(){...}
}
}
这样,可以轻松自然地模拟依赖关系,并且您可以专注于测试代码,而无需使用任何棘手的第三方库。
还有其他解决方案(百老汇,建筑师等)可以为您提供帮助。尽管他们可能做的比您想要的更多,或使用起来更混乱。
TypeDI是这里提到的最甜的,请在TypeDI中查看此代码
import "reflect-metadata";
import {Service, Container} from "typedi";
@Service()
class SomeClass {
someMethod() {
}
}
let someClass = Container.get(SomeClass);
someClass.someMethod();
看看下面的代码:
import {Container, Service, Inject} from "typedi";
// somewhere in your global app parameters
Container.set("authorization-token", "RVT9rVjSVN");
@Service()
class UserRepository {
@Inject("authorization-token")
authorizationToken: string;
}
Google的di.js可在Node.js(+浏览器)(+ ES6)上运行
我长期使用.Net,PHP和Java,因此我也想在NodeJS中使用方便的依赖注入。人们说,NodeJS中的内置DI足够了,因为我们可以通过Module获得它。但这并不令我满意。我想保留一个模块不超过一个类。另外,我希望DI完全支持模块生命周期管理(单模块,瞬态模块等),但是对于Node模块,我不得不经常编写手动代码。最后,我想简化单元测试。这就是为什么我为自己创建了一个依赖注入。
如果您正在寻找DI,请尝试一下。可以在这里找到:https : //github.com/robo-creative/nodejs-robo-container。完全记录在案。它还解决了DI的一些常见问题以及如何以OOP方式解决它们。希望能帮助到你。
这取决于您的应用程序的设计。显然,您可以执行类似Java的注入操作,在其中创建类的对象,并在构造函数中传递这样的依赖关系。
function Cache(store) {
this._store = store;
}
var cache = new Cache(mysqlStore);
如果您不使用JavaScript进行OOP,则可以创建一个初始化函数来设置所有内容。
但是,您可以采用另一种方法,这种方法在基于事件的系统(例如node.js)中更为常见。如果您可以对应用程序建模(仅在大多数情况下)仅对事件起作用,那么您所需要做的就是设置一切(我通常通过调用init函数来完成)并从存根发出事件。这使得测试相当容易且可读。
了解下垂(Node.js的一个简单但功能强大的依赖项注入和实体(文件)管理框架)
我认为我们仍然需要在Node.js中进行依赖注入,因为它可以放宽服务之间的依赖关系,并使应用程序更清晰。
受到Spring Framework的启发,我还实现了自己的模块以支持Node.js中的依赖注入。我的模块还能够检测code changes
和auto reload
服务,而无需重新启动应用程序。
请访问我的项目:Buncha-IoC容器
谢谢!
The reality is that you can test your node.js without IoC container because JavaScript is a really dynamic programming language and you can modify almost everything at run-time.
Consider the following:
import UserRepository from "./dal/user_repository";
class UserController {
constructor() {
this._repository = new UserRepository();
}
getUsers() {
this._repository.getAll();
}
}
export default UserController;
So you can override the coupling between components at run-time. I like to think that we should aim to decouple our JavaScript modules.
The only way to achieve real decoupling is by removing the reference to the UserRepository
:
class UserController {
constructor(userRepository) {
this._repository = userRepository;
}
getUsers() {
this._repository.getAll();
}
}
export default UserController;
This means that somewhere else you will need to do the object composition:
import UserRepository from "./dal/user_repository";
import UserController from "./dal/user_controller";
export default new UserController(new UserRepository());
I like the idea of delegating the object composition to an IoC container. You can learn more about this idea in the article The current state of dependency inversion in JavaScript. The article tries to debunk some "JavaScript IoC container myths":
Myth 1: There is no place for IoC containers in JavaScript
Myth 2: We don’t need IoC containers, we already have module loaders!
Myth 3: Dependency inversion === injecting dependencies
If you also like the idea of using an IoC container you could take a look to InversifyJS. The latest release (2.0.0) supports many use cases:
您可以在InversifyJS上了解更多有关它的信息。
require
是在Node.js中管理依赖项的方法,它肯定是直观且有效的,但也有其局限性。
我的建议是看一下当今可用于Node.js的一些依赖注入容器,以了解它们的优缺点。他们之中有一些是:
仅举几个。
现在真正的问题是,与简单的容器相比,使用Node.js DI容器可以实现什么require
?
优点:
缺点:
require
绝对不使用就好像您偏离了Node的思维方式。As with anything related to software development, choosing between DI or require
depends on your requirements, your system complexity, and your programming style.
我还编写了一个模块来完成此任务,称为rewire。只需使用npm install rewire
,然后:
var rewire = require("rewire"),
myModule = rewire("./path/to/myModule.js"); // exactly like require()
// Your module will now export a special setter and getter for private variables.
myModule.__set__("myPrivateVar", 123);
myModule.__get__("myPrivateVar"); // = 123
// This allows you to mock almost everything within the module e.g. the fs-module.
// Just pass the variable name as first parameter and your mock as second.
myModule.__set__("fs", {
readFile: function (path, encoding, cb) {
cb(null, "Success!");
}
});
myModule.readSomethingFromFileSystem(function (err, data) {
console.log(data); // = Success!
});
我受到Nathan MacInnes的注射器的启发,但使用了不同的方法。我不用vm
来评估测试模块,实际上我使用节点自己的需求。这样,您的模块的行为就像使用一样require()
(除了您的修改)。此外,还完全支持调试。
我认为其他职位在使用DI的论点上做得很好。对我来说,原因是
在不知道其路径的情况下注入依赖项。这意味着,如果您更改磁盘上的模块位置或与另一个模块交换位置,则无需触摸依赖该模块的每个文件。
它使模拟测试依赖关系变得容易得多,而无需以
require
没有问题的方式重写全局函数的痛苦。它可以帮助您将应用程序组织和推理为松散耦合的模块。
但是我很难找到一个我和我的团队可以轻松采用的DI框架。所以我最近基于这些功能构建了一个名为deppie的框架
require
模块