使用node.js中的全局变量进行依赖注入

时间:2014-04-13 21:46:02

标签: node.js dependency-injection global-variables

我开始基于node.js的长期项目,所以我希望建立一个坚实的DI系统。 虽然node.js的核心意味着使用简单的模块require()来连接组件,但我发现这种方法不适合大型项目(例如,要求每个文件中的模块不是可维护的,可测试的或动态的。)

现在,在发布此问题之前,我已完成了一些研究,并且我已经为node.js找到了一些有趣的DI库(请参阅wire.jsdependable.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; 据说,全局变量是一种不好的做法,但在我看来,我似乎为单个全局变量的成本节省了大量的重复。

任何人都可以查看我的建议并建议反对吗?

谢谢!

2 个答案:

答案 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!感兴趣。