【问题标题】:How to return value from a promise that's inside another function?如何从另一个函数内部的 Promise 中返回值?
【发布时间】:2018-05-08 05:30:25
【问题描述】:

我知道有很多关于异步编程和 Promise 的问题,但我真的需要一个包含此特定代码的示例来弄清楚我应该如何返回在另一个函数中返回的 Promise。

我有两个功能。第一个在 GET'ing 路由时调用。此路线应创建付款链接并将预订保存到数据库。

exports.create_booking = function(req, res) {

      req.body.payment = exports.create_booking_payment(req.body.total_amount);

      console.log(req.body.payment); // This returns ' Promise { <pending> } '

      var new_booking = new Booking(req.body);
      new_booking.save(function(err, booking) {
        if (err)
          res.send(err);
        res.json(booking);
      });

};

但是,使用异步方法创建支付链接。我的第一个问题是我只能在方法回调函数中访问付款。

现在我已经将该方法封装在另一个(异步)方法中,在该方法中创建并解析了 Promise。这个方法被返回给我的第一个方法,带有一个 await 语句,但所有返回的是:' Promise { }'。

我知道发生这种情况是因为在解决承诺之前返回了该方法。但我不明白为什么会这样。我的假设是“await”语句确保在异步函数完成之前等待返回方法。

exports.create_booking_payment = async function() {

function asyncPayment() {
  return new Promise (function(resolve, reject) {

      mollie.payments.create({
          amount:      20.00,
          description: "Reservation code: ",
          redirectUrl: "https://www.website.com/",
          webhookUrl:  ""
        }, function(payment) {
              if (payment.error) reject(payment.error)
              else { resolve({
                  id: payment.id,
                  link: payment.getPaymentUrl(),
                  status: payment.status
                })
              }
      });

   });
 }

 return await asyncPayment();

}

希望有人能帮帮我...

【问题讨论】:

    标签: javascript node.js asynchronous


    【解决方案1】:

    您似乎错过了async 函数仍然返回一个承诺,而不是实际值。因此,当您调用create_booking_payment() 时,您将得到一个承诺,即您需要使用.then()await。跨功能边界没有免费的午餐。 await 允许您在函数内以类似同步的方式进行编程,但仍然不允许您从函数返回值。当您从 async 函数返回值时,实际上是在返回一个解析为该值的承诺。

    所以,您可以使用 asyncawait

    exports.create_booking = async function(req, res) {
    
       try{
          req.body.payment = await exports.create_booking_payment(req.body.total_amount);
    
          console.log(req.body.payment);
    
          var new_booking = new Booking(req.body);
          new_booking.save(function(err, booking) {
            if (err)
              res.status(500).send(err);
            else 
              res.json(booking);
          });
       } catch(e) {
          res.status(500).send(err);
       } 
    };
    

    或者这个.then():

    exports.create_booking = function(req, res) {
    
          exports.create_booking_payment(req.body.total_amount).then(payment => {    
              console.log(payment);
              req.body.payment = payment;
              var new_booking = new Booking(req.body);
              new_booking.save(function(err, booking) {
                if (err)
                  res.status(500).send(err);
                else 
                  res.json(booking);
             });
        }).catch(err => {
            res.status(500).send(err);
        });
    
    };
    

    注意,我还为这两种情况添加了更完整的错误处理。此外,如果您“承诺”或为您的 .save() 方法使用已经承诺的接口,则此代码会更简洁。我非常不喜欢在基于 Promise 的代码中使用普通的回调异步代码,因为它最终会重复错误处理(就像您在本例中看到的那样)。


    另外,create_booking_payment() 不需要是async 或使用await,因为您需要它做的就是返回您已经知道如何做的承诺:

    exports.create_booking_payment = function() {
    
      return new Promise (function(resolve, reject) {
    
          mollie.payments.create({
              amount:      20.00,
              description: "Reservation code: ",
              redirectUrl: "https://www.website.com/",
              webhookUrl:  ""
            }, function(payment) {
                  if (payment.error) reject(payment.error)
                  else { resolve({
                      id: payment.id,
                      link: payment.getPaymentUrl(),
                      status: payment.status
                    })
                  }
          });
    
       });
    
    }
    

    【讨论】:

    • 有了这个,函数exports.create_booking_payment函数不需要async,返回不需要await,因为它返回一个promise
    • @Kaddath - 是的,没错,我加了。
    猜你喜欢
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2020-03-28
    • 2023-02-10
    相关资源
    最近更新 更多