Node.js 在函数外使用Mongodb变量
因此,我正在制作一个web应用程序,我试图将变量发送到一个EJS文件,但是当它们从mongo函数中发送出来时,它们会显示为未定义的,因为出于某种原因,它是一个不同的范围。这很难解释,所以让我给你看看Node.js 在函数外使用Mongodb变量,node.js,mongodb,express,ejs,Node.js,Mongodb,Express,Ejs,因此,我正在制作一个web应用程序,我试图将变量发送到一个EJS文件,但是当它们从mongo函数中发送出来时,它们会显示为未定义的,因为出于某种原因,它是一个不同的范围。这很难解释,所以让我给你看看 router.get("/", function(req, res){ var bookCount; var userCount; Books.count({}, function(err, stats){ if(err){ console.log
router.get("/", function(req, res){
var bookCount;
var userCount;
Books.count({}, function(err, stats){
if(err){
console.log("Books count failed to load.");
}else{
bookCount = stats;
}
});
User.count({}, function(err, count){
if(err){
console.log("User count failed to load.")
}else{
userCount = count;
console.log(userCount);
}
});
console.log(userCount);
//Get All books from DB
Books.find({}, function(err, allbooks){
if(err){
console.log("Problem getting all books");
}else{
res.render("index", {allbooks: allbooks, bookCount: bookCount, userCount: userCount});
}
});
});
因此,在User.Count和Books.Count中,我找到了一个集合中有效的文档数量,该数量存储在最上面声明的变量中
在分配了像userCount这样的数字后,我使用了console.log(userCount)
,它输出正确的数字,即3
,如果要执行console.log(userCount)
,它将返回undefined
,这是对最顶部声明的引用
真正奇怪的是,
Book.Find()
拥有正确的userCount
,尽管这是一个完全不同的函数。我试图实现的整个目标是执行res.render(“index”,{userCount:userCount})代码>在书籍的外部。查找()
。我可以这样做,但由于某种原因,它通过了未定义的,而不是3
。我希望这有点道理。我似乎找到了解决办法。但如果有人知道另一种方式,我很想知道。因此,基本上您所需要做的就是将User.Count函数移到router.get()函数之外。这是一个典型的异步操作问题:您的方法(Books.count
,Books.find
,User.count
)会立即被调用,但传递给它们的回调函数不会被调用userCount
在您的日志中是未定义的
,因为console.log
在回调函数赋值之前被调用。您的代码类似于:
var userCount;
setTimeout(function() {
userCount = 3;
}, 1000);
console.log(userCount); // undefined
User.count
在返回结果之前需要时间执行,就像setTimeout
在调用其回调之前需要指定的时间执行一样。问题是JS不会暂停并等待超时完成,然后再继续并调用下面的console.log,它会调用setTimeout
,然后立即调用console.log
,一秒钟后调用回调函数
要渲染完整视图,需要确保在调用res.render
之前拥有所有数据。为此,您需要等待所有方法回调,然后再调用res.render
。但是等等,我刚刚告诉过你JS不会停下来等待,那么这是如何实现的呢<代码>承诺
就是答案。事实上,有很多承诺
看起来您使用的是猫鼬模型。编写Mongoose的目的是,如果不向方法传递回调函数,它们将返回一个承诺
Books.count({}) // returns a promise
jspromises有一个方法then
,该方法接受一个回调函数,当promise已用异步方法调用的值解析时,该函数将被调用
Books.count({}) // takes some time
.then(function(bookCount) { // called when Books.count is done
// use the bookCount here
})
问题是,您希望在继续之前等待多个操作和多个承诺完成。幸运的是,JS有一个专门用于此目的的实用程序:
Promise.all( // wait for all of these operations to finish before calling the callback
Books.count({}),
User.count({}),
Books.find({})
)
.then(function(array) { // all done!
// the results are in an array
bookCount = array[0];
userC0unt = array[1];
allBooks = array[2];
})
欺骗