【问题标题】:Promises and async/await combination, ideal way to wait for asynchronous operations?Promise 和 async/await 组合,等待异步操作的理想方式?
【发布时间】:2019-11-14 08:01:12
【问题描述】:

在函数中单独使用 async/await 会返回一个“待定值”,但如果使用了 Promise,那么最终将返回实际值。这是等待异步操作完成的理想方式吗?

这正是我想要的结果

    var foundForm = await getDocument(query) //Returns the resulting document


 async function getDocument(query){
 return new Promise((resolve,reject) =>{
 MongoClient.connect  (url, async function(err, db) {
if (err) throw err;
 console.log(query)
db.collection("users").find(query).toArray(function(err, result) {
  if (err) {
    console.log(err)
    throw err;
  }
  console.log(result);
  db.close();
  resolve(result) //   returns result;


       });
     });
  })
 }

这不会返回我需要的内容:

      var foundForm = await getDocument(query) //Returns 'pending'


    async function getDocument(query){

      MongoClient.connect  (url, async function(err, db) {
        if (err) throw err;
    console.log(query)
        db.collection("users").find(query).toArray(function(err,                            result) {
    if (err) {
    console.log(err)
    throw err;
  }
  console.log(result);
    db.close();

   return result;
     });

     })

}

【问题讨论】:

  • 您能否使用edit 澄清一下您的代码示例。此外,据我所知,您的内部 MongoClient.connect 回调不需要async,因为您不需要等待任何东西。我敢说没有理想的处理方式,async/await 是 promise 实现的语法糖,只是处理一些人们不喜欢的关于 promise 链的事情。您在第二段代码中获得的待处理只是因为您没有解决或拒绝,所以它们是您如何编写该代码的错误
  • 第一个函数立即返回一个解析为回调结果的 Promise,第二个函数什么也不返回,return result; 是从回调中返回而不是 getDocument() 函数
  • @WilliamLohan 当然!现在这很有意义

标签: javascript node.js asynchronous


【解决方案1】:

由于您的 getDocument 代码需要等待不提供 Promise 接口的异步操作,因此 getDocument 不应该是 async 函数,因为您需要手动创建 Promise。 (而且你给一个不以承诺为中心的函数的回调几乎不应该是一个async 函数。)

function getDocument(query){
    return new Promise((resolve,reject) =>{
        MongoClient.connect(url, function(err, db) {
            if (err) {
                // Reject, don't throw
                reject(err);
                return;
            }
            console.log(query);
            db.collection("users").find(query).toArray(function(err, result) {
                if (err) {
                    // Reject, don't throw
                    reject(err);
                    return;
                }
                console.log(result);
                db.close();
                resolve(result);
            });
        });
    });
}

或者,使用启用承诺的MongoClient.connectdb.collection("users").find 版本。 MongoDB 现在在其 JavaScript API 中提供了这些(恐怕我没有详细信息)。然后你会使用async 函数和awaitsomething 像这样(根据this blog post):

// BE SURE TO DOUBLE-CHECK THE DETAILS
async function getDocument(query){
    const db = await MongoClient.connect(url);
    const await result = db.collection("users").find(query).toArray();
    console.log(result);
    await db.close(); // No idea whether you need `await` here or not
    return result;
}

【讨论】:

  • (你给一个非承诺为中心的函数的回调应该几乎永远不会是一个异步函数。) - 为什么这被认为是坏的?这样做会有什么后果?
  • MongoDB javascript API sn-p 看起来干净清爽,很棒
  • @d12 - 因为async 函数总是返回一个promise,但是如果他们返回这个promise 的东西对promise 没有任何作用,它会让你遇到未处理的拒绝错误。它还会误导你(和你的潜在读者),给人的印象是你返回承诺的东西会用它做一些有用的事情。一个典型的例子是人们在数组上使用forEach 并传入async 回调,然后想知道为什么所有数组条目在第一个完成工作之前都通过forEach。 :-)
  • 太棒了,现在说得通了!
【解决方案2】:

简而言之,是的。如果您的目标是支持 es6 async/await 的平台并希望使用它,那么如果库仅公开回调 api,那么将回调“包装”在 Promise(您的第一个函数)中就是您实现该目标的方式。虽然您首先要确保该库不提供基于 Promise 的 api,但您可以从库中返回 Promise 并等待。

【讨论】:

    猜你喜欢
    • 2018-02-15
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 2020-09-22
    • 1970-01-01
    相关资源
    最近更新 更多