Javascript 异步mongoDB find()方法存在问题

Javascript 异步mongoDB find()方法存在问题,javascript,node.js,mongodb,express,ejs,Javascript,Node.js,Mongodb,Express,Ejs,我试图从mongoDB获取一些数据并将其存储在一个数组中,然后将该数组传递到ejs文件中。问题似乎是,当mongo查询结果时,db代码执行后的代码将被删除,并向ejs发送一个空数组。结果在执行渲染函数之后出现,因此不会向ejs发送任何数据 app.get('/', (req, res) => { var batData = []; //console.log("get req"); MongoClient.connect(url, (err,db)=>{

我试图从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
    });


 });
输出的顺序如下: 输入DB 出口数据库 查询成功

预期订单: 输入DB 查询成功
Exit DB

batData被声明为数组,但随后在代码中将其设置为与find查询相等。您应该将其改为.push(),或者将其保存到一个新变量中,然后将其保存到.push()中


另外,在batData上使用const(而不是var)会抛出一个错误,从而显示这个错误。除非您使用var来支持较旧的代码,否则请改用const和let。

batData被声明为数组,但稍后在代码中您将其设置为等于find查询。您应该将其改为.push(),或者将其保存到一个新变量中,然后将其保存到.push()中


另外,在batData上使用const(而不是var)会抛出一个错误,从而显示这个错误。除非您使用var来支持较旧的代码,否则请使用const和let。

在此处使用promise

//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完成,您也可以处理这个问题
  • AsyncWait只是以一种更简洁的方式处理promise的一种方法,可以从代码中删除回调hell
  • 无论何时需要使用wait,都必须将其函数标记为异步,正如我在app.get回调函数中所做的那样
  • 现在等待将阻止代码,直到完成、拒绝或解决为止
  • 然后,它将转到代码的res.render部分

    • 在这里使用承诺

      //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完成,您也可以处理这个问题
      • AsyncWait只是以一种更简洁的方式处理promise的一种方法,可以从代码中删除回调hell
      • 无论何时需要使用wait,都必须将其函数标记为异步,正如我在app.get回调函数中所做的那样
      • 现在等待将阻止代码,直到完成、拒绝或解决为止
      • 然后,它将转到代码的res.render部分

      我在前面使用了.push()方法,得到了相同的结果。Find()返回一个游标,toArray()将其转换为数组。对,我应该用let。谢谢是的,你说得对-我忘了它正在把它转换成数组。看起来你遵循了Arpit的建议,将其转化为承诺,这当然是正确的答案。很高兴你找到了答案。:)我在前面使用了.push()方法,得到了相同的结果。Find()返回一个游标,toArray()将其转换为数组。对,我应该用let。谢谢是的,你说得对-我忘了它正在把它转换成数组。看起来你遵循了Arpit的建议,将其转化为承诺,这当然是正确的答案。很高兴你找到了答案。:)将find()更改为find().toArray((err,data)=>{…}),它成功了!我知道mongo函数可以通过回调或承诺来执行。我一直在等待一个回调解决方案,但这也可以工作,看起来更干净。谢谢你,把find()改成find().toArray((呃,data)=>{…}),它成功了!我知道mongo函数可以通过回调或承诺来执行。我一直在等待一个回调解决方案,但这也可以工作,看起来更干净。谢谢你,伙计。