NodeJS Express 依赖注入和数据库连接

NodeJS Express Dependency Injection and Database Connections

来自非 Node 背景,我的第一直觉是这样定义我的服务

MyService.js

module.exports = new function(dbConnection)
{
    // service uses the db
}

现在,我希望每个请求打开一个数据库连接,所以我在中间件中定义:

res.locals.db = openDbConnection();

并且在一些消费快递api代码中:

api.js

var MyService = require(./services/MyService')

...

router.get('/foo/:id?', function (req, res) {
    var service = new MyService(res.locals.db);
});

现在,由于 Node 首选的依赖注入方法是通过 require(...) 语句,因此我似乎不应该使用 MyService 的构造函数来注入 db.

假设我想要

var db = require('db');

MyService 的顶部,然后使用 db.current 之类的方式......但是现在 [=16= 我将如何将数据库绑定到当前 res.locals 对象] 本身就是一个模块?在 Node 中处理这种瘦身的推荐方法是什么?

更新答案:2015 年 2 月 5 日

如果您想将数据库连接附加到每个请求对象,然后在您的服务中使用该连接,则必须以某种方式将连接传递给 myService。下面的例子展示了一种方法。如果我们尝试使用 db.current 或类似的东西,我们将在我们的 DB 模块中存储状态。根据我的经验,这会导致麻烦。

或者,我在 中列出了我已经使用(并且仍在使用)的方法。对于此示例,这意味着以下内容:

// api.js
var MyService = require(./services/MyService')

...

router.get('/foo/:id?', function (req, res) {
    MyService.performTask(req.params.id);
});


// MyService.js
var db = require('db');
module.exports = {
   performTask: function(id)
      {
         var connection = db.getOpenConnection();
         // Do whatever you want with the connection.
      }
}

通过这种方法,我们将 DB 模块与 api/app/router 模块分离,只有实际使用它的模块才会知道它的存在。

上一个答案:2015 年 5 月 1 日

您所说的可以使用快速中间件来完成。它可能是这样的:

var db = require('db');

// Attach a DB connection to each request coming in
router.use(req, res, next){
   req.locals.db = db.getOpenConnection();
   next();
}

// Later on..
router.get('/foo/:id?', function (req, res) {
  // We should now have something attached to res.locals.db!
  var service = new MyService(res.locals.db);
});

我个人以前从未在快递申请中见过 new MyService 这样的东西。这并不意味着它不能完成,但你可以考虑这样的方法

// router.js
var MyService = require('MyService');
router.get('/foo/:id?', function (req, res) {
  MyService.foo(res.locals.db);
});

// MyService.js
module.exports.foo(connection){
  // I have a connection!
}