从Node.js中的mongodb异步访问数据时出现问题

时间:2019-06-30 11:56:16

标签: node.js mongodb

在下面的代码中,我只是从mongodb访问一些数据并将其存储在变量中。现在,我想在CustomCardView函数中使用此变量。但是当我尝试将其简单地显示为mongodb.connect()

我知道这是JavaScript异步内容。我浏览过多个有关回调,承诺和异步/等待的网站,但我听不懂这些主题。

任何人都可以对我的代码进行一些简单的修改。

undefined

预期输出:app.get('/',function(req,res){ var data; mongodb.connect(url,{useNewUrlParser:true},(err,db)=>{ var dbo=db.db('pract') var cursor=dbo.collection('samp').find({_id:1410}) cursor.forEach(function(doc){ data=doc; }) }) console.log(data) res.end() })

实际输出:{name:'vasu',age:20}

2 个答案:

答案 0 :(得分:1)

我建议您使用从最近的Javascript版本开始引入的新async await functionality。由于它看起来像普通的同步代码,因此更易于推理。掌握Javascript的异步细微差别将花费一些时间,但是最终您将需要它来了解Javascript如何使用多种异步方法(承诺,回调等)工作。

我能想到的使用express&MongoDB的最短的异步/等待代码是这样的:

const MongoClient = require('mongodb').MongoClient
const express = require('express')
const app = express()
var conn

app.get('/', async (req, res) => {
  var output = await conn.db('test').collection('test').find().toArray()
  res.send(output)
})

var run = async function() {
  conn = await MongoClient.connect('mongodb://localhost:27017/test', {useNewUrlParser: true})
  await app.listen(3000)
  console.log('listening on 3000')
}

run()

使用curl "http://localhost:3000"应该在test数据库中打印test集合的内容。

一些注意事项:

  • conn是一个全局变量,允许MongoDB驱动程序正确使用连接池。一次连接,然后在各处重复使用连接。不要为每个请求一直连接到数据库。
  • 主要的run()方法建立数据库连接,然后开始侦听。这样,您可以确保数据库已准备就绪。否则,您的应用程序可以在数据库准备就绪之前开始监听。
  • 上面的示例代码没有任何错误处理方法。在真实代码中,应根据需要使用try {...} catch {...}

此代码已在节点12.4.0,MongoDB节点驱动程序3.2.7和Express 4.17.1上进行了测试

如果发现此代码无效,请确保可以连接到数据库。

答案 1 :(得分:0)

一旦收到GET请求,您的应用程序就连接到数据库。这是异步工作。因此需要一些时间才能得到结果。但是console.log不会等待此异步操作。

因为连接到数据库操作将被发送到事件循环。 console.log具有比事件循环更高的优先级。因此console.log将首先执行,并且在执行过程中,数据没有任何值,因此它返回的是undefined。(我只是碰触了事件循环,这是您应该了解的问题)。

解决方案:

app.get('/',function(req,res){
    //var will make it global, avoid using var.
    let data;
    mongodb.connect(url,{useNewUrlParser:true},(err,db)=>{
        var dbo=db.db('pract')
        var cursor=dbo.collection('samp').find({_id:1410})
        cursor.forEach(function(doc){
            data=doc;
            console.log(data)
          //we are inside the for each function which is inside the callback db function. 
          //that means console.log is inactive till connection is successfully done. 
          //find function is also async function but console.log cannot access to data from here. 
         //it can access only one level above function's variables. 
         //forEach function is sync so it will run the data=doc first then console.log the data. 
         //make sure you already have the data inside the connected database.
        })
    }) 

    res.end()
})

此语法非常古老。尝试学习promise和async / await