在Node.js中将公共variables传递到单独模块的最佳方式是什么?
我使用单独的路由器文件作为主应用程序和身份validation应用程序模块。 我不能得到最好的方式来传递variables(数据库客户端)到路由器。 我不想硬编码或传递:
module.exports = function(app, db) {
也许这是使用单例注册或使用全局数据库variables的最好方法?
什么是你的devise模式的经验? 哪种方式最好,为什么?
我发现使用dependency injection来传递东西,是最好的风格。 这确实看起来像你有:
// App.js module.exports = function App() { }; // Database.js module.exports = function Database(configuration) { }; // Routes.js module.exports = function Routes(app, database) { }; // server.js: composition root var App = require("./App"); var Database = require("./Database"); var Routes = require("./Routes"); var dbConfig = require("./dbconfig.json"); var app = new App(); var database = new Database(dbConfig); var routes = new Routes(app, database); // Use routes.
这有很多好处:
- 它迫使你将系统分离成具有清晰依赖关系的组件,而不是隐藏文件中间的依赖关系,它们被称为
require("databaseSingleton")
或者更糟糕的是global.database
。 - 它使得unit testing变得非常简单:如果我想单独testing
Routes
,我可以注入假app
和database
参数,并且只testingRoutes
代码本身。 - 它将所有的对象图布线放在一个地方,即组合根(在本例中是
server.js
,应用程序入口点)。 这给你一个地方,看看如何在系统中的一切都融合在一起。
我所看到的更好的解释之一就是采访 .NET着作“ dependency injection”一书的作者Mark Seeman 。 它同样适用于JavaScript,尤其适用于Node.js: require
常常用作传统的服务定位器,而不仅仅是一个模块系统。
我build议你用db实例创build一个设置文件,以及其他你需要在全局中使用的东西,比如“singleton”。
例如,我有我的redis数据库客户端settings.js:
var redis = require('redis'); exports.redis = redis.createClient(6379, '127.0.0.1');
而在其他多个模块中,我将它包括在内:
var settings = require('./settings'); setting.redis.<...>
很多时候,我总是有一个db连接的实例。
如果您使用dependency injection框架,您可以节省自己的所有模板代码
这个答案列出了其中的一些。 我也在这里构build了一个更简单的DI框架 。
编辑:下面是一个复制forms的情况下,页面更改的答案
require
是在Node.js中pipe理依赖关系的方式,当然它是直观和有效的,但也有其局限性。
我的build议是查看一下Node.js中的一些dependency injection容器,以了解它们的优缺点。 他们之中有一些是:
- 分散
- 电解液
- 线
- 静脉
- Pongular
仅举几个。
现在真正的问题是,与一个简单的require
相比,你能用Node.js DI容器实现什么?
优点:
- 更好的可testing性:模块接受它们的依赖作为input
- 控制反转:决定如何连接你的模块而不接触你的应用程序的主代码。
- 用于parsing模块的可定制algorithm:依赖关系具有“虚拟”标识符,通常它们不绑定到文件系统上的path。
- 更好的可扩展性:由IoC和“虚拟”标识符启用。
- 其他花哨的东西可能:
- asynchronous初始化
- 模块生命周期pipe理
- DI容器本身的可扩展性
- 可以轻松实现更高级别的抽象(例如AOP)
缺点:
- 不同于Node.js的“体验”:不
require
使用肯定会感觉你正在偏离Node的思维方式。 - 依赖与其实现之间的关系并不总是明确的。 依赖关系可以在运行时解决,并受各种参数的影响。 代码变得更难理解和debugging
- 启动时间较慢
- 成熟度(目前):目前没有一款解决scheme真的很受欢迎,所以没有太多的教程,没有生态系统,没有经过testing。
- 一些DI容器在Browserify和Webpack等模块打包程序中效果不佳。
这是完全过时的,但你可以在脚本中使用global
:
global.foo = new Foo();
在另一个脚本中:
foo.bar();
你也可以使用已经存在的常量:
Object.foo = new Foo();
和这里 :
Object.foo.bar();