所以我正在创建一个Web应用程序,我正在尝试将变量发送到EJS文件,但是当它们被发送出mongo函数时,它们会被定义为未定义,因为由于某种原因它是不同的范围。这很难解释,所以让我试着告诉你。
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
,如果要从User.count函数中做console.log(userCount)
它会返回{{ 1}},它是对最顶层声明的引用。
真正奇怪的是undefined
具有正确的Book.Find()
,即使它是一个完全不同的功能。我试图完成的整个目标是在userCount
之外进行res.render("index", {userCount: userCount});
。我可以这样做但当然由于某种原因它通过了Books.find()
而不是undefined
。我希望这有点意义。
答案 0 :(得分:0)
我似乎找到了解决方案。但如果有人知道我想知道的另一种方式。所以基本上你需要做的就是在router.get()函数之外移动User.Count函数。不完全确定它的逻辑,但它的工作原理......
答案 1 :(得分:0)
这是一个典型的异步操作问题:您的方法(Books.count
,Books.find
,User.count
)会立即被调用,但您传递给它们的回调函数则不会。您的日志中userCount
为undefined
,因为在回调函数中的赋值之前调用了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没有暂停等待,那么如何实现呢? Promise
就是答案。实际上是多重承诺。
看起来你正在使用Mongoose模型。编写了Mongoose,这样如果你没有将回调函数传递给你的方法,它们就会返回一个promise。
Books.count({}) // returns a promise
JS promises有一个方法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];
})