node.js Express js,mongodb:“ReferenceError:db is not defined”当在post函数之外提到db时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34566049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Express js,mongodb: "ReferenceError: db is not defined" when db is mentioned outside post function
提问by R-R
The index.js file:
index.js 文件:
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.
当使用var user=db.collection('user')external 时router.post,它会给出错误,但是当使用同一个 inside 时router.post,它工作正常。
what might be the concept I am missing here?
我在这里缺少的概念可能是什么?
Edit: part of App.js file involving mongodb
编辑:涉及 mongodb 的 App.js 文件的一部分
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
}
});
回答by Arnold Daniels
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.
记住MongoClient.connect()是异步的。数据库连接可能在您准备就绪时尚未准备就绪var user=db.collection('user');。数据库连接已在回调完成后建立,不早于此。
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.
请注意,连接是在第一个 require 上进行的,因此如果您require('database.js');在 App.js 中添加。您不会在第一个请求中丢失 。
Alternatively you can use promises, which takes care of the waiting logic for you.
或者,您可以使用promises,它会为您处理等待逻辑。
回答by Joost Vunderink
What you are missing is the timing of execution.
您缺少的是执行时间。
The var userline outside router.postis executed immediately when index.jsis processed by node.js.
var user外面的行在被 node.js 处理router.post时立即执行index.js。
The var userline inside router.postis only executed when a client requests the /page of your app.
仅当客户端请求您的应用程序页面时才执行var user里面的行。router.post/
The dbvariable is only assigned after the connection to your MongoDB has been made successfully. This is too late for the first var userline, but in time for the first HTTP request to /.
db仅在成功连接到 MongoDB 后才分配该变量。这对于第一var user行来说已经太晚了,但是对于第一个发送到/.
回答by Anand S
MongoClient.connect's callback function is called asynchronously only after it is connected to the database. At the time only you are defining dbas a global variable.
MongoClient.connect的回调函数只有在连接到数据库后才会异步调用。当时只有您定义db为全局变量。
Assuming you require index.js file in app.js. The line var user=db.collection('user');outside router.postis executed synchronously. By the time this line is executed dbwould have not be defined.
假设您在 app.js 中需要 index.js 文件。var user=db.collection('user');外面的行router.post是同步执行的。到执行此行时db,还没有定义。
The line var user=db.collection('user');inside router.postis executed asynchronously. So, when that code is executed db is already defined.
var user=db.collection('user');里面的行router.post是异步执行的。因此,当执行该代码时,db 已经定义。
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
我建议您了解异步 javascript 执行https://stackoverflow.com/a/7104633/3492210

