首页 > 解决方案 > 异步 mongoDB find() 方法的问题

问题描述

我正在尝试从 mongoDB 获取一些数据并将其存储在一个数组中,然后将该数组传递给 ejs 文件。问题似乎是mongo在查询结果时,db代码执行后的代码,给ejs发送了一个空数组。结果是在执行渲染函数之后出现的,因此没有数据发送到 ejs..

app.get('/', (req, res) => {

    var batData = [];
    //console.log("get req");

    MongoClient.connect(url, (err,db)=>{
        if(err) throw err;

        console.log("Enter DB");

        var dbo = db.db("MatchDB");

        batData = dbo.collection("Batting").find().toArray((err,res)=>{
                console.log("Query Success");
        });

       console.log("Exit DB");


    db.close();
    })

    //  batData remains empty when these lines of code executes.
    res.render('index', {
        batting: batData
    });


 });

输出顺序如下: Enter DB Exit DB Query Success

预期顺序:进入数据库查询成功退出数据库

标签: javascriptnode.jsmongodbexpressejs

解决方案


在这里使用承诺

//change your query to function

functon query(){
 //now here return a promise
 return new Promise((resolve, reject) => {
   MongoClient.connect(url, (err,db)=>{
    if(err) reject(err) // reject the err

    var dbo = db.db("MatchDB");

    dbo.collection("Batting").find( (err, data) => {
            console.log("Query Success");
            batData = data//save your data here or do anything
            db.close(); //close the db
            resolve(batData) //this will get returned to the caller
    });//dbo find ends

  }) //mongo client ends
 })//promise end
}//function ends

//now in your app.get route

// see here i marked this async, for using await
app.get('/', async (req, res) => {

    let batData = await query() // this will wait until it gets resove or rejected

    res.render('index', {
        batting: batData // now you will have data here
    });


});

这里有几点可以帮助你

  • 承诺被解决或拒绝
  • Promise 的调用者函数将等待它从 Promise 函数返回结果,如果您不想等待 Promise 完成,您可以再次处理此问题
  • 异步等待只是以更简洁的方式处理承诺的方法,从代码中删除回调地狱
  • 每当您需要使用 await 时,您必须标记其异步所在的函数,正如您在 app.get 回调函数中所做的那样
  • 现在 await 将阻塞代码,直到它完成、拒绝或解决
  • 之后它将转到代码的 res.render 部分

推荐阅读