我目前正在用nodejs创建一些实验性项目。我用Spring编写过很多Java EE web应用程序,非常欣赏依赖注入的便利性。
现在我很好奇:如何对节点进行依赖注入?或者:我真的需要它吗?因为编程风格不同,是否存在替代概念?
到目前为止,我谈论的是一些简单的事情,比如共享数据库连接对象,但我还没有找到一个让我满意的解决方案。
我目前正在用nodejs创建一些实验性项目。我用Spring编写过很多Java EE web应用程序,非常欣赏依赖注入的便利性。
现在我很好奇:如何对节点进行依赖注入?或者:我真的需要它吗?因为编程风格不同,是否存在替代概念?
到目前为止,我谈论的是一些简单的事情,比如共享数据库连接对象,但我还没有找到一个让我满意的解决方案。
当前回答
Node.js和其他平台一样需要DI。如果您正在构建一些大的东西,DI将使您更容易模拟代码的依赖关系并彻底测试代码。
例如,数据库层模块不应该只在业务代码模块中使用,因为在单元测试这些业务代码模块时,dao将加载并连接到数据库。
一种解决方案是将依赖项作为模块参数传递:
module.exports = function (dep1, dep2) {
// private methods
return {
// public methods
test: function(){...}
}
}
通过这种方式,依赖关系可以轻松自然地模拟,你可以专注于测试你的代码,而不需要使用任何棘手的第三方库。
还有其他的解决方案(百老汇,建筑师等)可以帮助你解决这个问题。尽管他们可能做的比你想要的多,或者使用更多的杂物。
其他回答
我认为我们仍然需要Nodejs中的依赖注入,因为它放松了服务之间的依赖关系,使应用程序更加清晰。
受Spring Framework的启发,我也实现了自己的模块来支持Nodejs中的依赖注入。我的模块还能够检测代码更改并自动重新加载服务,而无需重新启动应用程序。
访问我的项目:Buncha - IoC容器
谢谢你!
它应该像这样灵活和简单:
var MyClass1 = function () {}
var MyClass2 = function (myService1) {
// myService1.should.be.instanceof(MyClass1);
}
container.register('myService1', MyClass1);
container.register('myService2', MyClass2, ['myService1']);
我写过一篇关于node.js中的依赖注入的文章。
管理你的服务-node.js依赖注入 包文档在这里
我希望它能帮到你。
我是在回答我自己的DI模块上的一个问题时发现这个问题的,这个问题是为什么有人需要一个DI系统来进行NodeJS编程。
答案显然倾向于这篇文章中给出的答案:这要看情况。这两种方法都有折衷之处,阅读这个问题的答案可以让你更好地了解它们。
所以,这个问题的真正答案应该是,在某些情况下,你会使用依赖注入系统,在其他情况下则不会。
也就是说,作为开发人员,您希望的是不要在各种应用程序中重复使用您的服务。
这意味着我们应该编写一些可以在依赖注入系统中使用但不绑定到依赖注入库的服务。对我来说,这意味着我们应该像这样编写服务:
module.exports = initDBService;
// Tells any DI lib what it expects to find in it context object
// The $inject prop is the de facto standard for DI imo
initDBService.$inject = ['ENV'];
// Note the context object, imo, a DI tool should bring
// services in a single context object
function initDBService({ ENV }) {
/// actual service code
}
这样你的服务就可以工作了,不管你是和谁一起使用 没有依赖注入工具。
看看dips(一个简单而强大的Node.js依赖注入和实体(文件)管理框架)
https://github.com/devcrust/node-dips
我还写了一个模块来完成这一点,它被称为rewire。只需使用npm安装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()完全相同(除了您的修改)。此外,完全支持调试。