Reputation: 347
The index.js file:
var express = require('express');
var router = express.Router();
function validCheck (exp,name) {
return exp.test(name);
}
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index');
});
var user=db.collection('user'); //gives reference error,db is not defined
router.post('/',function(req,res,next){
username=req.body.username;
password=req.body.password;
//var user=db.collection('user'); //works fine
user.findOne({'username':username,'password':password},function(err,docs){
//do something
});
});
module.exports = router;
When using var user=db.collection('user')
outside router.post
, it gives the error but when the same is used inside router.post
, it works fine.
what might be the concept I am missing here?
Edit: part of App.js file involving mongodb
var mongodb= require('mongodb');
var MongoClient= mongodb.MongoClient;
var URL = 'mongodb://127.0.0.1:27017/mainDB';
MongoClient.connect(URL,function(err,database){
if(!err){
db=database;
}
else{
//do something
}
});
Upvotes: 1
Views: 60030
Reputation: 687
var mongo = require('mongodb');
var url = "mongodb://localhost:27017/qanda";
mongo.MongoClient.connect(url, function(err, db) {
if (err) throw err;
console.log("Database created!");
db.close();
});
Upvotes: 0
Reputation: 1138
MongoClient.connect
's callback function is called asynchronously only after it is connected to the database. At the time only you are defining db
as a global variable.
Assuming you require index.js file in app.js. The line var user=db.collection('user');
outside router.post
is executed synchronously. By the time this line is executed db
would have not be defined.
The line var user=db.collection('user');
inside router.post
is executed asynchronously. So, when that code is executed db is already defined.
To your question:
what might be the concept I am missing here?
I suggest you to learn about asynchronous javascript execution https://stackoverflow.com/a/7104633/3492210
Upvotes: 0
Reputation: 16583
Remember MongoClient.connect()
is async. The database connection might not be ready at the time you do var user=db.collection('user');
. The database connection has been made one the callback is done, no earlier than that.
When the first request is done, the database connection just happens to be established. The longer you wait the more likely it is that is works, but still it's the wrong approach.
Also working with global variables is bad practice and leads to confusion and other problems.
In short the code should look like
// module database.js
var mongodb= require('mongodb');
var MongoClient= mongodb.MongoClient;
var URL = 'mongodb://127.0.0.1:27017/mainDB';
var db;
var error;
var waiting = []; // Callbacks waiting for the connection to be made
MongoClient.connect(URL,function(err,database){
error = err;
db = database;
waiting.forEach(function(callback) {
callback(err, database);
});
});
module.exports = function(callback) {
if (db || error) {
callback(error, db);
} else {
waiting.push(callback);
}
}
}
Than use it like
var db = require('database.js');
router.post('/',function(req,res,next){
username=req.body.username;
password=req.body.password;
db.conn(function(err, database) {
if (err) {
res.sendStatus(500);
console.log(err);
return;
}
database.collection('users').findOne({'username':username, 'password':password}, function(err, docs){
//do something
});
});
});
Note that the connection is made on the first require, so if you add require('database.js');
in App.js. You don't loose the on the first request.
Alternatively you can use promises, which takes care of the waiting logic for you.
Upvotes: 1
Reputation: 1236
What you are missing is the timing of execution.
The var user
line outside router.post
is executed immediately when index.js
is processed by node.js.
The var user
line inside router.post
is only executed when a client requests the /
page of your app.
The db
variable is only assigned after the connection to your MongoDB has been made successfully. This is too late for the first var user
line, but in time for the first HTTP request to /
.
Upvotes: 0