在Nodejs中dependency injection的模型

将依赖关系注入模型的最佳做法是什么? 特别是,如果他们的getter是asynchronous的,就像mongodb.getCollection()

重点是一次注入依赖关系

 var model = require('./model')({dep1: foo, dep2: bar}); 

并调用所有成员方法而不必将它们作为parameter passing。 我也不希望每个方法都以asynchronous获取者的瀑布开始。

我结束了一个专用的exports包装,代理所有的调用,并传递asynchronous依赖。

然而,这会造成很多开销,这是重复的,我通常不喜欢它。

 var Entity = require('./entity'); function findById(id, callback, collection) { // ... // callback(null, Entity(...)); }; module.exports = function(di) { function getCollection(callback) { di.database.collection('users', callback); }; return { findById: function(id, callback) { getCollection(function(err, collection) { findById(id, callback, collection); }); }, // ... more methods, all expecting `collection` }; }; 

注入依赖关系的最佳实践是什么,特别是那些使用asynchronous获取者的?

如果您的需要是支持unit testing,那么像JavaScript这样的dynamic语言中的dependency injection可能比它的价值更麻烦。 请注意,几乎所有您需要的模块都可能使用Java,.NET和其他静态编译语言中的DI模式。

如果你想嘲笑行为,以隔离特定的代码单元进行testing,请参阅“sinon”模块http://sinonjs.org/ 。 它允许你dynamic地交换进/出拦截器,这些拦截器可以监视方法调用或者完全replace它们。 在实践中,你会在需要模块的地方写一个摩卡testing,然后需要一个在你的代码中使用的模块。 使用sinon在该模块上窥探或存储一个方法,结果就可以隔离你的代码。

有一种情况是我无法将第三方代码与sinon完全隔离,这就是require()模块的行为执行一些你不想在你的testing中运行的行为。 在这种情况下,我创build了一个名为“mockrequire”的超级简单模块https://github.com/mateodelnorte/mockrequire ,它允许您提供一个内联模拟而不是实际的模块。 您可以提供一个使用sinon的间谍或存根的模拟,并且具有与所有其他testing相同的语法和模式。

希望这回答您的post潜在的问题。 ;)

在非常简单的情况下,可以简单地导出一个修改文件范围内的对象的函数,并返回实际的导出对象,但是如果要注入更多variables(即从应用程序中多次使用),通常最好创build一个包装对象就像你做的一样。

在某些情况下,可以使用包装类而不是返回对象的函数来减less一些开销和缩进。

例如

 function findById(id, callback, collection) { // ... // callback(null, Entity(...)); }; function Wrapper(di) { this.di = di; } module.exports = Wrapper; // or do 'new' usage in a function if preferred Wrapper.prototype.findById = function (id, callback) { // use this.di to call findById and getCollection }, // etc 

除此之外,改善事情并不是一件容易的事情。 我喜欢这个方法。 保持状态di显式,并从findById的函数体中分离出来,并通过使用一个类来至less减less缩进的嵌套。