Node.js 在函数外使用Mongodb变量

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

因此,我正在制作一个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
,如果要执行
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];
    })
欺骗