如何从另一个函数内的承诺返回值?

Nvd*_*B31 1 javascript asynchronous node.js

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

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

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);
      });

};
Run Code Online (Sandbox Code Playgroud)

然而,创建支付链接是通过异步方法进行的。我的第一个问题是我只能在方法回调函数中访问付款。

现在我已将该方法包装在另一个(异步)方法中,在该方法中创建并解析了 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();

}
Run Code Online (Sandbox Code Playgroud)

我希望有人能在这里帮助我...

jfr*_*d00 5

你似乎错过了一个async函数仍然返回一个承诺,而不是实际值。所以,当你调用 时create_booking_payment(),你会得到一个你需要使用.then()with 或awaitwith的 promise 。跨功能边界没有免费的午餐。 await允许您在函数内部以类似同步的方式编程,但仍然不允许您从函数返回值。当看起来您正在从async函数返回值时,您实际上是在返回一个解析为该值的承诺。

所以,你可以用asyncand做到这一点await

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);
   } 
};
Run Code Online (Sandbox Code Playgroud)

或者这与.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);
    });

};
Run Code Online (Sandbox Code Playgroud)

请注意,我还为这两种情况添加了更完整的错误处理。此外,如果您“承诺”或为您的.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
                })
              }
      });

   });

}
Run Code Online (Sandbox Code Playgroud)