【问题标题】:Why does my function comprised of asynchronous functions not returning correct value? (NodeJS)为什么我的函数由不返回正确值的异步函数组成? (NodeJS)
【发布时间】:2019-09-09 21:45:30
【问题描述】:

在异步函数中分配的变量没有返回预期的输出。

我目前正在编写一个 NodeJS 函数,该函数从 MongoDB 数据库中查找一个对象(该数据库运行良好)并在找到时返回一个对象。问题是包含异步函数的函数不会等到前面的函数完成。我对 JS 和 NodeJS 比较陌生,所以我可能误解了异步函数的作用。

async function findUserByEmail (userEmail) {
    var mg = require('mongodb').MongoClient;

    var user;

    await mg.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, async function(err, db){
        var dbo = db.db(myDB);
        var query = { email : userEmail };

        await dbo.collection("Users").findOne(query).then((result)=>{
            user = result;
            db.close();
        });
    });

    return user;
}

我试图在“findOne(query)”函数中返回分配给“用户”的值,但是,返回的值始终是“未定义”。

【问题讨论】:

  • 您可以使用var user = await mg.connect.... 获取它,并在db.close() 之后使用return await dbo.collection....return result;。但我很好奇为什么它不能这样工作。
  • 您当前的节点版本是多少?您可以尝试使用其他版本,它可能已在某些版本中修复。
  • 我使用的是 6.9.0 版本。我也试过你的第一条评论,但似乎仍然存在同样的问题
  • 您可以尝试升级到节点8.16.0,例如使用包n。 (npm install -g n && n 8.16.0)
  • 我会试试的,谢谢。

标签: node.js async-await


【解决方案1】:

您正在混合使用回调和异步调用。所以让我把它清理干净。瞧,这里你做了一些应该工作的东西(你有一些我不知道的值,例如 myDB 和 url)。

async function findUserByEmail (userEmail) {
    var mg = require('mongodb').MongoClient;
    var db = await mg.connect(url, { useNewUrlParser: true, useUnifiedTopology: true });
    var result;

    // Add a Try/Catch to capture any errors, 
    // such that the database can still be closed
    try {  
        var dbo = db.db(myDB);
        var query = { email : userEmail };
        result = await dbo.collection("Users").findOne(query);
    } catch (error) {
        throw error;   
    } finally {
        db.close();
    }
    return result;
}

注意:我建议在应用程序启动时打开一次 MongoDB 连接,在它因任何原因关闭时重新打开它,并在应用程序停止时关闭它,因为为每个请求打开一个新连接会增加一些巨大的开销(想想可能会慢 25 倍)。

【讨论】:

  • 可能需要一个try/catch,这样如果前面的任何await 语句被拒绝,您就可以关闭数据库。
  • @jfriend00 我同意,但总的来说,我不建议在与获取函数相同的函数中打开和关闭数据库连接。它有一些显着的开销。
  • 现在你正在“吃掉”错误,并且如果查询拒绝,不让调用者看到被拒绝的承诺。
  • 好的,你现在明白了。顺便说一句,我同意不仅为一个查询打开和关闭数据库连接的概念。仅供参考,您不需要catch,除非您想在那里记录错误。只需 try/finally 就可以了。
猜你喜欢
  • 2013-09-27
  • 2020-08-30
  • 2020-10-17
  • 2021-04-12
  • 1970-01-01
  • 2021-10-06
  • 2015-09-13
  • 1970-01-01
  • 2015-08-24
相关资源
最近更新 更多