NodeJS Express Dependency Injection and Database C

2019-05-31 14:35发布

Coming from a non Node background, my first instinct is to define my service as such

MyService.js

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

Now, I want one open db connection per request, so I define in middleware:

res.locals.db = openDbConnection();

And in some consuming Express api code:

api.js

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

...

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

Now, being that Node's preferred method of dependency injection is via the require(...) statement, it seems that I shouldn't be using the constructor of MyService for injection of the db.

So let's say I want to have

var db = require('db');

at the top of MyService and then use somehow like db.current....but how would I tie the db to the current res.locals object now that db is a module itself? What's a recommended way of handling this kind of thin in Node?

1条回答
ら.Afraid
2楼-- · 2019-05-31 15:27

Updated Answer: 05/02/15

If you want to attach a DB connection to each request object, then use that connection in your service, the connection will have to be passed to myService some how. The example below shows one way of doing that. If we try to use db.current or something to that effect, we'll be storing state in our DB module. In my experience, that will lead to trouble.

Alternatively, I lay out the approach I've used (and still use) in this previous answer. What this means for this example is the following:

// 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.
      }
}

With this approach, we've decoupled the DB module from the api/app/router modules and only the module that actually uses it will know it exists.

Previous Answer: 05/01/15

What you're talking about could be done using an express middleware. Here's what it might look like:

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);
});

I personally have never seen something like new MyService before in express applications. That doesn't mean it can't be done, but you might consider an approach like this

// 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!
}
查看更多
登录 后发表回答