【问题标题】:NodeJS ASync call of MongoClient GetData routineMongoClient GetData 例程的 NodeJS ASync 调用
【发布时间】:2020-12-15 17:36:49
【问题描述】:

下面的代码是https://www.w3schools.com/nodejs/nodejs_mongodb_find.asp的混合代码 和 https://stackoverflow.com/questions/49982058/how-to-call-an-async-function#:~:text=Putting%20the%20async%20keyword%20before,a%20promise%20to%20be%20resolved.

当您查看代码下方的 console.log 时,事情似乎出现了问题。我认为通过使函数异步并使用 .then 可以避免这些问题。

我希望 MongoDB 数据检索功能与 app.get 功能分开。 没有数据返回到 get 请求。我猜 app.get 代码在函数返回值之前失败并结束。我需要更正什么?

async function getLanguageTranslationData(fromLanguage, toLanguage) {
    console.log("Started getLanguageTranslationData")
    const databaseUrl = "mongodb://localhost:27017"
    const databaseName = 'MyCompanyPOC'
    
    mongoClient.connect(databaseUrl, function(err, conn) {
        if (err) throw err; 
        const collectionName = "Phrases";
        var dbo = conn.db(databaseName)
        var query = 
                { $and: 
                       [ {masterLanguage: fromLanguage},
                         {localizedLanguage: toLanguage} 
                       ]
                }
        console.log("query=" + JSON.stringify(query)); 
        console.log("about to retrieve data"); 
        dbo.collection(collectionName).find(query).toArray( 
             function(err, result) {
                  if (err) throw err; 
                  console.log("Back from mongoDB.find()")
                  console.log(JSON.stringify(result))
                  return result 
                  conn.close()
           }) 
    })  
}


app.get("/api/gettranslations/:fromLanguage/:toLanguage", 
        async function(req, res) {
  console.log("Backend: /api/gettranslations method started: " + 
     " fromLanguage=" + req.params.fromLanguage + 
     " toLanguage=" + req.params.toLanguage)
  
  getLanguageTranslationData(
                             req.params.fromLanguage, 
                             req.params.toLanguage)
        .then((arrayResult) => { 
           console.log("got arrayResult back from getLanguageTranslationData")
           res.status(200).json(arrayResult)
           console.log("Backend: End of /api/gettranslations process")
         })
}) 

Node.JS 控制台输出:

listening on port 3001
Backend: /api/gettranslations method started:  fromLanguage=en-US toLanguage=es-MX
Started getLanguageTranslationData
(node:44572) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
got arrayResult back from getLanguageTranslationData
Backend: End of /api/gettranslations process
query={"$and":[{"masterLanguage":"en-US"},{"localizedLanguage":"es-MX"}]}
about to retrieve data
Back from mongoDB.find()
[{"_id":"5f403f7e5036d7bdb0adcd09","masterLanguage":"en-US","masterPhrase":"Customers","localizedLanguage":"es-MX","localizedPhrase":"Clientes"},{ etc... 

【问题讨论】:

  • 在您的代码中,getLanguageTranslationData 不返回任何内容,因此.then 立即执行,arrayResult === undefined。有很多方法可以重构您的代码以使其工作,但我想最简单的方法就是放弃getLanguageTranslationData 并将其代码移回app.get,除非您在其他地方需要它 - 在这种情况下您应该考虑调用mongoClient.connect()getLanguageTranslationData 之外,所以你可以将后者设为return dbo.collection(collectionName).find(query).toArray()
  • 谢谢。那么“返回结果”算不算返回呢?我试图减少嵌套代码的数量并追踪右括号/括号错误。最终,它可能是另一个模块中的数据访问层。
  • 这可能是我想要做的。它使用回调。我会试试看:stackoverflow.com/questions/35246713/…

标签: javascript node.js async-await


【解决方案1】:

问题是 getLanguageTranslationData 应该返回一个 promise 以便您可以将它用作处理程序中的承诺,但在您的情况下,调用 getLanguageTranslationData 将返回未定义,因为此函数中的所有代码都将执行异步由于 nodejs non-blocking 性质。

所以你可以做的是像这样从你的getLanguageTranslationData 函数返回承诺。

function getLanguageTranslationData(fromLanguage, toLanguage) {
    const databaseUrl = "mongodb://localhost:27017"
    const databaseName = 'MyCompanyPOC'
    
    return new Promise((resolve, reject)=>{
        mongoClient.connect(databaseUrl, function(err, conn) {
            if (err) reject(err); 
            else{
                const collectionName = "Phrases";
                var dbo = conn.db(databaseName)
                var query = 
                        { $and: 
                               [ {masterLanguage: fromLanguage},
                                 {localizedLanguage: toLanguage} 
                               ]
                        }
                dbo.collection(collectionName).find(query).toArray( 
                     function(err, result) {
                          if (err) reject(err); 
                          else
                          resolve(result);    
                   }) 
            }
           
        }) 
    }) 
}

然后在你的处理程序中使用 await 来使用返回的承诺

app.get("/api/gettranslations/:fromLanguage/:toLanguage", 
  async function(req, res) {
      try{
        let arrayResult = await getLanguageTranslationData(req.params.fromLanguage, req.params.toLanguage);
        res.status(200).json(arrayResult)
      }catch(err){
        // return error
      }
}) 

以上代码将为您提供您需要做什么的要点,实际代码可能会根据您的需要而有所不同。

你可以参考hereasync-await

【讨论】:

  • 谢谢,看看我的其他回答。我在你发帖的同时打字和测试。最新的驱动程序支持承诺,我参考的链接显示了两种方式。
【解决方案2】:

我以这种方式工作,基于以下示例:Node.js, Mongo find and return data

@Namar 的回答可能也是正确的,但我在他发布的同时测试了这个。正如上面的 StackOverflow 问题/答案所述,最新版本的 MongoClient 支持 Promise。那篇文章还展示了如何放入一个单独的模块,这可能是我本周晚些时候要做的事情。

function getLanguageTranslationData(fromLanguage, toLanguage) {
    console.log("Started getLanguageTranslationData")
    const databaseUrl = "mongodb://localhost:27017"
    const databaseName = 'ShedCompanyPOC'
    
    return mongoClient.connect(databaseUrl)
        .then(function(conn) {
            var collectionName = "UploadedDataeFromExcel";
            var dbo = conn.db(databaseName)
            var query = 
                    { $and: 
                           [ {masterLanguage: fromLanguage},
                             {localizedLanguage: toLanguage} 
                           ]
                    }
            console.log("query=" + JSON.stringify(query)); 
            console.log("about to retrieve data"); 
            var collection = dbo.collection(collectionName)
            return collection.find(query).toArray(); 
        }).then(function(result) {
              console.log("Back from mongoDB.find()")
              console.log(JSON.stringify(result))
              //conn.close()
              return result
        }); 
    }



app.get("/api/gettranslations/:fromLanguage/:toLanguage", 
        async function(req, res) {
  console.log("Backend: /api/gettranslations method started: " + 
     " fromLanguage=" + req.params.fromLanguage + 
     " toLanguage=" + req.params.toLanguage)
  
  getLanguageTranslationData(
                             req.params.fromLanguage, 
                             req.params.toLanguage)
        .then(function(arrayResult) {
           console.log("got arrayResult back from getLanguageTranslationData")
           res.status(200).json(arrayResult)
           console.log("Backend: End of /api/gettranslations process")
         }, function(err) {
             console.log("The promise was rejected", err, err.stack)
         })
}) 

【讨论】:

    猜你喜欢
    • 2014-08-19
    • 2019-02-17
    • 1970-01-01
    • 2017-07-02
    • 2014-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多