【问题标题】:Problem in accessing the data from mongodb in node.js asynchronously从node.js中的mongodb异步访问数据的问题
【发布时间】:2019-06-30 11:56:16
【问题描述】:

在下面的代码中,我只是从 mongodb 访问一些数据并将其存储在一个变量中。现在我想在 mongodb.connect() 函数之外使用这个变量。但是当我尝试它时,它只是将输出显示为 @987654322 @。

我知道这是 javascript 异步的东西。我浏览了几个关于回调、承诺和异步/等待的网站,但我无法理解这些主题中的任何一个。

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

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}

实际输出:undefined

【问题讨论】:

    标签: node.js mongodb


    【解决方案1】:

    我建议您使用在最近的 Javascript 版本中引入的新 async await functionality 开始。这种形式更容易推理,因为它看起来像一个普通的同步代码。掌握 Javascript 的异步细微差别需要一些时间,但最终您将需要它来了解 Javascript 如何使用多种异步方法工作:Promise、回调等。

    我能想到的使用 express 和 MongoDB 的最短 async/await 代码是这样的:

    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 进行测试

    如果您发现此代码不起作用,请确保您可以连接到数据库。

    【讨论】:

      【解决方案2】:

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

      因为连接数据库操作将被发送到事件循环。 console.log 比事件循环具有更高的优先级。所以console.log将首先执行,在执行过程中,数据没有价值,所以它返回未定义。(我只是触摸了事件循环,这是你应该知道的关于你的问题)。

      解决方案:

      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

      【讨论】:

        猜你喜欢
        • 2015-06-20
        • 2023-03-04
        • 1970-01-01
        • 2020-03-27
        • 2013-03-25
        • 2015-02-19
        • 1970-01-01
        • 2017-08-11
        • 1970-01-01
        相关资源
        最近更新 更多