最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Sharing objects and avoiding globals in node.js - Stack Overflow

programmeradmin1浏览0评论

What would be the most appropriate way of sharing the database connection in the below snippet ( the db variable) with my routers/controllers without turning the db variable into a global?

var mongo = require('mongoskin'),
db = mongo.db(config.db.adress);

app.use(function(req, res, next) {
    db.open(function(err, data) {
        (err) ? res.send('Internal server error', 500) : next();
    });
});

// Setting up controllers here
app.post('/users', require('./controllers/users').create);

Coming from a PHP background, I came to think about Dependency Injection, but I have no idea if that's appropriate in node.

What would be the most appropriate way of sharing the database connection in the below snippet ( the db variable) with my routers/controllers without turning the db variable into a global?

var mongo = require('mongoskin'),
db = mongo.db(config.db.adress);

app.use(function(req, res, next) {
    db.open(function(err, data) {
        (err) ? res.send('Internal server error', 500) : next();
    });
});

// Setting up controllers here
app.post('/users', require('./controllers/users').create);

Coming from a PHP background, I came to think about Dependency Injection, but I have no idea if that's appropriate in node.

Share Improve this question edited Mar 14, 2012 at 10:48 Industrial asked Mar 14, 2012 at 10:08 IndustrialIndustrial 42.8k71 gold badges201 silver badges292 bronze badges 6
  • I don't see a problem??? It IS available inside the inner function already, in your example. If you don't specify a function inline but call one imported from another module instead, just give it to that function as parameter, possibly putting the call to that (external) fn inside an anonymous fn as already shown in your example. – Mörre Commented Mar 14, 2012 at 10:32
  • After your edit: give it to the function called from the "require"-d file as parameter (and make sure to actually use that param there, e.g. to set a module-global var to remember it for that module's other functions). Or, give it as parameter to any function who need DB access - which would be cleaner programming anyway (up to a point, that is). – Mörre Commented Mar 14, 2012 at 10:49
  • Well, sorry for the confusion. I updated the code in my question to contain an example of my routes/controller setup. There's no problem with the error handling, but I am still quite confused of what I should do to access the db object from inside the users controller, in this case, without first turning db into an global. – Industrial Commented Mar 14, 2012 at 10:50
  • Hi again. Not sure what you mean with module-global. Do you mind posting an answer showing your idea? – Industrial Commented Mar 14, 2012 at 10:52
  • Using your already existing example code, for that (main) module variables mongo and db are globally available for all other code you write in the same file. So at the top of your other module you could just declare another variable "db" and inside the create() function write the value received as parameter (which must have another name or it overwrites the outer-scope "db") into it. – Mörre Commented Mar 14, 2012 at 10:53
 |  Show 1 more comment

4 Answers 4

Reset to default 7

Try look at this way:

app.js:

var mongo = require('mongoskin'),
db = mongo.db(config.db.adress);

app.use(function(req, res, next) {
    db.open(function(err, data) {
        (err) ? res.send('Internal server error', 500) : next();
    });
});

require('./controllers/users')(app, db);

controllers/users.js:

module.exports = function (app, db) {

    app.post('/users', function(req, res, next) {
        // Your create function
        // Link to db exists here
    });

};

I don't have any experience with mongoskin but Mongoose neatly sidesteps this problem by returning a Singleton instance of Mongoose every time you require it.

Which allows you to create a connection once (on app init, usually) and simply use it by querying Models when you need it.

It also allows you to define your models once like this:

var mongoose = require('mongoose'),

  TodoSchema = new mongoose.Schema({
    title: { 'type': String, 'default': 'empty todo...' },
    order: { 'type': Number },
    done: { 'type': Boolean, 'default': false }
  });

mongoose.model('Todo', TodoSchema);

And then use them wherever you need to like this:

  var mongoose = require('mongoose'),
      Todo = mongoose.model('Todo');

More information on how Mongoose works like this, with example code can be found in this answer here.

From mongoskin's docs, it looks like you have to connect each time you want to use it, which you could simplify by wrapping the db connection in a file you can require:

db.js

exports.db = require('mongoskin').db('myProject-' + process.env.NODE_ENV);

use it:

var db = require('./db');

db.open(function(err, data) {
        (err) ? res.send('Internal server error', 500) : next();
    });

The method above, where db is passed as an argument to every function that may need it, leads to callback soup and should be avoided if possible.

I ended up using Vadim Baryshev's answer and took it a bit further by creating a State module holding commonly used modules together, to keep things tidy:

state.js:

module.exports = {
    mongo: require('mongoskin'),
    db: require('mongoskin').db('myProject-' +process.env.NODE_ENV )
} 

app.js:

var state = require('./state');
require('./controllers/Users')(app, state);

controllers/users.js:

module.exports = function (app, state) {

    app.post('/users', function(req, res, next) {
        state.db.find({}, function(doc, err) {});
    });

};

As suggested by @Jed Watson, the moongoose module uses a singleton (anti?) pattern, which is enforced by the require/export mechanism. Here is the specific bit of code :

(as found here : https://github.com/LearnBoost/mongoose/blob/master/lib/index.js)

/*!
 * The exports object is an instance of Mongoose.
 *
 * @api public
 */

var mongoose = module.exports = exports = new Mongoose;
发布评论

评论列表(0)

  1. 暂无评论