由于猫鼬查询/承诺而无法获取所需数据

时间:2019-03-25 10:03:27

标签: javascript node.js mongoose

我正在尝试创建类似Jeopardy的游戏。我在数据库中有游戏的主题。打开页面时,我希望它从数据库中随机获取6个主题。我将它们放在一个数组中,然后将其传递给我的ejs文件。问题是,当我将数组传递给ejs文件时,它始终为空。我了解这是由于猫鼬的承诺(实际上是查询)。我的问题是我不知道该如何处理。我已经阅读了Mongoose的文档,并在所有地方进行了搜索,但我无法弄清楚。

我已经尝试过使用回调,但是它们通常只会使程序挂起并且什么也不做。我曾尝试使用.then,但我一定使用错了,因为它无法满足我的要求。

app.get("/", function(request, response){
    //My array to put the topics into
    var questionArr = [];
    //I need to know the number of items in db for random
    var getQuestions = Questions.countDocuments({}, function(err, count){
        for(var i = 0; i < 6; i++){
            !function(i){
                var rand = math.randomInt(count);
                //Here I get a random topic and add to array
                //Seems to work and actually get it
                Questions.findOne().skip(rand).exec(function(err, result){
                    questionArr.push(result);
                });
            }(i);
        }
    });

    //I thought this would make it wait for the function to finish so
    //that I could have my full array, but apparently not
    getQuestions.then(() => {
        //this runs before the other functions and give me a length of 0
        console.log(questionArr.length);
        response.render("jeopardy.ejs", {questions: questionArr});
    });
});

我只需要在从数据库中获取信息后运行渲染即可。但是,它仍然只在一个空数组下运行。感谢您的帮助,我是异步的新手。

1 个答案:

答案 0 :(得分:1)

我发现您的代码有几个问题:

1)您正在混合promise和回调,这使事情变得更加复杂。该代码不起作用主要是因为您不等待Questions.findOne()结果。

2)没有Math.randomInt

要使其正常运行,必须与下面类似:

Questions.countDocuments()
    .then((count) => {
        return Promise.all([...new Array(6)].map(() => {
            const rand = Math.floor(Math.random() * Math.floor(count));
            return Questions.findOne().skip(rand).exec();
        }))
    })
    .then((questionArr) => {
        response.render("jeopardy.ejs", {questions: questionArr});
    });

最好是使用async / await,这将使其更具可读性

app.get("/", async function(request, response){
    const count = await Questions.countDocuments();
    const questionArr = await Promise.all([...new Array(6)].map(() => {
        const rand = Math.floor(Math.random() * Math.floor(count));
        return Questions.findOne().skip(rand).exec();
    }));
    response.render("jeopardy.ejs", {questions: questionArr});
});

还请记住,最好进行适当的错误处理,但这是另一篇文章的主题:)