使用Mongodb变量的功能

时间:2017-03-14 00:46:23

标签: 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("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。我希望这有点意义。

2 个答案:

答案 0 :(得分:0)

我似乎找到了解决方案。但如果有人知道我想知道的另一种方式。所以基本上你需要做的就是在router.get()函数之外移动User.Count函数。不完全确定它的逻辑,但它的工作原理......

答案 1 :(得分:0)

这是一个典型的异步操作问题:您的方法(Books.countBooks.findUser.count)会立即被调用,但您传递给它们的回调函数则不会。您的日志中userCountundefined,因为在回调函数中的赋值之前调用了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];
    })