Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to export an object that only becomes available in an async callback?

I have a db.js file in which I set up a MongoDB connection. I would like to export the database object into my main app.js file:

// db.js
require('mongodb').MongoClient.connect(/* the URL */, function (err, db) {
    module.exports = db;
});

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

app.get('/', function (req, res) {
    db.collection(/* … */); // throws error
});

The error is:

TypeError: Object # has no method 'collection'

So, how can I export the db object properly?

like image 680
Šime Vidas Avatar asked Jan 05 '14 21:01

Šime Vidas


1 Answers

The best option, as suggested in the comments by elclanrs, is to export a promise:

// database.js
var MongoClient = require('mongodb').MongoClient,
    Q = require('q'),
    connect = Q.nbind(MongoClient.connect, MongoClient);

var promise = connect(/* url */);        

module.exports = {
  connect: function () {
    return promise;
  }
}

// app.js
var database = require('./database');

database.connect()
  .then(function (db) {
    app.get('/', function (req, res) {
      db.collection(/* … */);
    });
  })
  .catch(function (err) {
    console.log('Error connecting to DB:', err);
  })
  .done();

(I'm using awesome Q library here.)


Below's the old version of my answer, left for the sake of history (but if you don't want to use promises, instead of going that road, you should use Matt's answer).

Its downside is that it will open a connection each time you require('database.js) (bummer!)

// DO NOT USE: left for the sake of history

// database.js
var MongoClient = require('mongodb').MongoClient;

function connect(cb) {
  MongoClient.connect(/* the URL */, cb);
}

module.exports = {
  connect: connect
}

// app.js
var database = require('./database');

database.connect(function (err, db) {
  app.get('/', function (req, res) {
      db.collection(/* … */);
  });
});
like image 160
Dan Abramov Avatar answered Sep 18 '22 20:09

Dan Abramov