我开始基于node.js的长期项目,所以我希望建立一个坚实的DI系统。 虽然node.js的核心意味着使用简单的模块require()来连接组件,但我发现这种方法不适合大型项目(例如,要求每个文件中的模块不是可维护的,可测试的或动态的。)
现在,在发布此问题之前,我已完成了一些研究,并且我已经为node.js找到了一些有趣的DI库(请参阅wire.js,dependable.js)< / p>
然而,为了最大限度地简化和最小化重复,我提出了自己实施DI的建议:
你有一个模块di.js,它充当容器,并通过指向存储依赖项名称及其各自.js文件的映射的json文件进行初始化。 这已经为DI提供了动态特性,因为您可以轻松地交换测试/开发依赖项。 容器可以通过使用inject()函数返回依赖项,该函数查找依赖关系映射并使用它调用require()。
为简单起见,模块被分配给一个全局变量,即global。$ di,这样项目中的任何文件都可以通过调用$ di.inject()
<来使用容器/注入器。 / LI>这里是实施的要点:
di.js:
module.exports = function(path) {
this.deps = require(path);
return {
inject: function(name) {
if (!deps[name])
throw new Error('dependency "' + name + '" isn\'t registered');
return require(deps[name]);
}
};
};
依赖关系图json文件:
{
"vehicle": "lib/jetpack",
"fuel": "lib/benzine",
"octane": "lib/octane98"
}
根据开发/测试模式初始化主js文件中的$ di:
var path = 'dep-map-' + process.env.NODE_ENV + '.json;
$di = require('di')(path);
在某个文件中使用它:
var vehicle = $di.inject('vehicle');
vehicle.go();
到目前为止,我能想到使用这种方法的唯一问题是全局变量$ di; 据说,全局变量是一种不好的做法,但在我看来,我似乎为单个全局变量的成本节省了大量的重复。
任何人都可以查看我的建议并建议反对吗?
谢谢!
答案 0 :(得分:1)
总的来说,这个方法对我来说听起来不错。
全局变量在节点中的工作方式是,当您声明一个没有var
关键字的变量时,它会被添加到所有模块之间共享的global对象中。您还可以明确使用global.varname
。例如:
vehicle = "jetpack"
fuel = "benzine"
console.log(vehicle) // "jetpack"
console.log(global.fuel) // "benzine"
使用var
声明的变量只是模块的本地变量。
var vehicle = "car"
console.log(vehicle) // "car"
console.log(global.vehicle) // "jetpack"
因此,如果您正在执行$di = require('di')(path)
(没有var
),那么在您的代码中,您应该能够在其他模块中使用它而不会出现任何问题。使用global.$di
可能会使代码更具可读性。
答案 1 :(得分:1)
你的方法很简单明了。无论您是拥有全局变量还是每次都需要您的模块都不重要。
关于可测试性,它允许您使用模拟替换模块。对于单元测试,您应该添加一个功能,使您可以轻松地为每个测试应用不同的模拟。暂时扩展您的依赖关系图的东西。
如需进一步阅读,我可以推荐a great blog article on dependency injection in node.js以及a talk on the future dependency injector of angular.js,这是由一些严肃的主谋设计的。
顺便说一下,您可能对我实现的依赖注入容器Fire Up!感兴趣。