In your code:
// 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
});
You've called connect
in the db.js
class, yet it's asynchronous.
The call in app.js
to require
is synchronous in behavior though, so it will always receive an undefined value (as the exports
will not be assigned to a value at the time the db.js
has finished executing).
I'd suggest keeping things simple.
The option I usually use is something where the app code makes the connection and doesn't start listening for HTTP connections until it is complete. Then, I'll initialize each route
file by calling a named method and pass the database connection to it.
Or, you could just always call connect in each module, yet cache the value. (The connect call would need to be called within the route callback code so that the routes were defined immediately and not when the connection was actually established).
// db.js
var _db = null;
exports = function(callback) {
if (!_db) {
_db = {}; // only one connection, so we'll stop others from trying
require('mongodb').MongoClient.connect(/* the URL */, function (err, db) {
_db = db;
callback(err, db);
});
} else {
callback(null, _db);
}
};
// app.js
var db = require('./db');
db(function(err, connection) {
// store the connection value here and pass around, or ...
// call this always in each file ...
});
/// or ...
app.get('/', function (req, res) {
db(function(err, connection) {
connection.collection(/* … */);
});
});
Or, you could use MongooseJS (a wrapper for the native NodeJS MongoDB driver) where commands, etc. are queued if the connection isn't available yet ....