【发布时间】:2012-05-05 13:52:31
【问题描述】:
我使用单独的路由器文件作为主应用程序和身份验证应用程序的模块。我无法获得将变量(数据库客户端)传递到路由器的最佳方法。我不想硬编码或传递它:
module.exports = function(app, db) {
也许使用单例寄存器或使用全局 db 变量是最好的方法?
您对设计模式有何经验?哪种方式最好,为什么?
【问题讨论】:
我使用单独的路由器文件作为主应用程序和身份验证应用程序的模块。我无法获得将变量(数据库客户端)传递到路由器的最佳方法。我不想硬编码或传递它:
module.exports = function(app, db) {
也许使用单例寄存器或使用全局 db 变量是最好的方法?
您对设计模式有何经验?哪种方式最好,为什么?
【问题讨论】:
如果您使用依赖注入框架,您可以节省所有用于连接模块的样板代码
This answer 列出了其中的一些。我还建了一个simpler DI framework here。
编辑:以下是页面更改时的答案副本
require 是 Node.js 中管理依赖项的方式,它确实直观且有效,但也有其局限性。
我的建议是看一下目前可供 Node.js 使用的一些依赖注入容器,以了解它们的优缺点。其中一些是:
仅举几例。
现在真正的问题是,与简单的 require 相比,使用 Node.js DI 容器可以实现什么?
优点:
缺点:
require 肯定感觉你在偏离 Node 的思维方式。【讨论】:
完全过时了,但你可以使用global
在脚本中:
global.foo = new Foo();
在另一个脚本中:
foo.bar();
你也可以使用已经存在的常量:
Object.foo = new Foo();
这里:
Object.foo.bar();
【讨论】:
我发现使用依赖注入来传递东西是最好的风格。它确实看起来像你有的东西:
// 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。Routes,我可以使用伪造的app 和database 参数注入它并只测试Routes 代码本身。server.js,应用程序入口点)。这使您可以在一个地方查看所有内容如何在系统中组合在一起。我见过的对此更好的解释之一是an interview with Mark Seeman,他是优秀著作.NET 中的依赖注入 的作者。它同样适用于 JavaScript,尤其是 Node.js:require 通常用作经典的服务定位器,而不仅仅是模块系统。
【讨论】:
我建议您使用 db 实例以及您需要全局使用的其他内容(例如“singleton”)创建一个设置文件。
例如,我的 redis db 客户端有 settings.js:
var redis = require('redis');
exports.redis = redis.createClient(6379, '127.0.0.1');
我在其他多个模块中包含它:
var settings = require('./settings');
setting.redis.<...>
很多时候包括它我总是有一个数据库连接实例。
【讨论】: