Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing objects and avoiding globals in node.js

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.

like image 466
Industrial Avatar asked Mar 14 '12 10:03

Industrial


People also ask

Is using global variables bad in NodeJS?

Global variables are considered an anti-pattern in almost any programming language because they make it very hard to follow and debug code.

Can you explain globals in node JS?

Node. js Global Objects are the objects that are available in all modules. Global Objects are built-in objects that are part of the JavaScript and can be used directly in the application without importing any particular module.

Is the process a global object and can be accessed from anywhere in node JS?

A process object is a global object, which provides interaction with the current Node process and can be accessed from anywhere. In the following example, the exit event fires whenever the process is about to exit.


2 Answers

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

};
like image 143
Vadim Baryshev Avatar answered Oct 04 '22 21:10

Vadim Baryshev


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.

like image 44
Jed Watson Avatar answered Oct 04 '22 20:10

Jed Watson