【问题标题】:NodeJS Async/Await doesn't await (returns Promise pending)NodeJS Async/Await 不等待(返回 Promise 挂起)
【发布时间】:2019-05-07 17:36:54
【问题描述】:

我正在编写一个 API,它可以为用户获取 Stellar 网络上的过去交易,在我的数据库中查找相应的用户,然后将它们全部放在一个 JSON 中(以响应请求 - 稍后)。

问题:查找 accountID 对应的用户名(“from”字段)是 mongoose 的异步方法,仅在组装 JSON 后返回数据。

我尝试使用 async/await、promises、.thens,但似乎没有任何效果。

server.payments()
    .forAccount(accountId)
    .cursor('now')
    .order('desc')
    .limit(2)
    .call()
    .then(function (page) {
        var history = []
        for(var i = 0; i<page.records.length; i++){
            var obj = page.records[i]
            //Get the username corresponding to the key from my database
            //FIXME
            var username
            findUser(obj["from"]).then(result => {
                username = result
            })
            var payment = {
                "currency":obj["asset_code"],
                "from": obj["from"],
                "username":username,
                "amount": obj["amount"],
                "timestamp":obj["created_at"]
            }
            history.push(payment)
        }
        console.log(history)
        //console.log(JSON.stringify(history))
    })
    .catch((err) => {
        console.log(err)
    })

async function findUser(senderKey){
    var user = await mongoose.User.findOne({publicKey: senderKey})
    console.log(user.username)
    return user.username
}

预期结果:findUser 返回值,支付变量使用它并一起记录。

发生了什么:findUser 开始查找数据,支付变量被放在一起(用户名未定义)并记录,findUser 返回数据。

这是日志:(spiderman 是我数据库中的实际用户名)

[ { currency: 'MEUR',
    from: 'GACRQARPR2OMWRG6IH7HM5DYTA3FMM6UKA7NKS4BIJIADRIKFRPAIE7G',
    username: undefined,
    amount: '3.0000000',
    timestamp: '2019-05-07T13:37:04Z' },
  { currency: 'MEUR',
    from: 'GACRQARPR2OMWRG6IH7HM5DYTA3FMM6UKA7NKS4BIJIADRIKFRPAIE7G',
    username: undefined,
    amount: '2.0000000',
    timestamp: '2019-05-07T13:34:21Z' } ]
spiderman
spiderman

【问题讨论】:

    标签: node.js for-loop mongoose stellar


    【解决方案1】:

    高亮推荐,您可以根据自己的情况使用async/await 语法轻松实现。

    您将wait 直到服务器响应page,然后page.records 中的每个obj.map.forEach... 会让您变得一团糟),您wait findUser 函数返回username,然后做你的事。

    try {
      const page = await server.payments()
        .forAccount(accountId)
        .cursor('now')
        .order('desc')
        .limit(2)
        .call()
      const history = [];
      for (const obj of page.records) {
        const username = await findUser(obj["from"]);
        const payment = {
          "currency": obj["asset_code"],
          "from": obj["from"],
          "username": username,
          "amount": obj["amount"],
          "timestamp": obj["created_at"]
        }
        history.push(payment)
      }
      console.log(history)
    } catch (e) {
      console.log(e)
    }
    

    提醒:await 表达式只允许在 async 函数中使用。

    【讨论】:

      【解决方案2】:

      您可以将新的“for of”循环与异步等待一起使用:-

      server.payments()
          .forAccount(accountId)
          .cursor('now')
          .order('desc')
          .limit(2)
          .call()
          .then(async function (page) {
              var history = []
      
              for(const obj of page.records) {
                const username = await findUser(obj["from"]);
                  var payment = {
                      "currency":obj["asset_code"],
                      "from": obj["from"],
                      "username":username,
                      "amount": obj["amount"],
                      "timestamp":obj["created_at"]
                  }
                  history.push(payment)
              }
      
              console.log(history)
              //console.log(JSON.stringify(history))
          })
          .catch((err) => {
              console.log(err)
          })
      

      【讨论】:

      • 另外,bluebird 非常适合异步/等待循环。
      • 使用本地代码总是比使用比本地代码慢的外部库更好。
      • 我之前错过了 .then() 函数中的异步声明,这就是为什么当我尝试使用 await finduser() 时它不起作用的原因。成功了,谢谢。
      • 嗯,这很有趣@cEeNiKc,最后我记得,bluebird 实际上比 V8 更快更轻,因为它针对 Promise 进行了优化
      【解决方案3】:

      你需要一个条件来检查你等待的函数是否已经完成

      async function findUser(senderKey){
          var user = await mongoose.User.findOne({publicKey: senderKey})
          if (user){
            console.log(user.username)
            return user.username
          }
      }

      【讨论】:

      • 其实这不是迈克尔的问题。在迭代到下一次迭代之前,他根本没有等待 promise 解决。
      • 是的,这似乎也是我的问题。问题是,我不确定如何真正等待承诺。
      • 请检查我提供的解决方案。这会清除一些事情。
      猜你喜欢
      • 2020-08-03
      • 1970-01-01
      • 2018-05-16
      • 1970-01-01
      • 1970-01-01
      • 2017-09-11
      • 2021-12-11
      • 2016-03-08
      相关资源
      最近更新 更多