异步功能完成后执行其余功能

时间:2019-07-23 20:06:51

标签: javascript node.js asynchronous google-cloud-firestore stripe-payments

我想使用Stripe检索付款的最后4位数字。为此,我必须运行一个异步功能,并在此功能内另一个异步功能。 之后,我想用后4位数字更新数据库。但是我想在解决这两个功能后更新数据库,如果没有,我会得到一个undefined

if (intent.status === "succeeded") {
    const user = res.locals.decodedClaims;
    const uid = user.uid;
    let last4; //trying to set last4 to global var so that i can change it inside a function

    // The payment didn’t need any additional actions and completed!
    // Handle post-payment fulfillment

    //get payment last4 digits
    stripe.paymentIntents.retrieve(intent.id, function(err, paymentIntent) {
      // asynchronously called
      if (err) {
        return console.log("PI retrieve error: ", err);
      }
      stripe.charges.retrieve(paymentIntent.charges.data[0].id, function(
        err,
        charge
      ) {
        if (err) {
          return console.log("Charge retrieve error: ", err);
        }
        last4 = charge.payment_method_details.card.last4;
        console.log("charge: ", last4); // works, eg: 4242
      });
    });

    //update status in database
    const userRef = db.collection("users").doc(uid);
    let updatedStatus = userRef.update({
      paid: true,
      last4: last4 //undefined
    });

    updatedStatus.catch(err => {
      console.log(err);
    });
    //send success message to client
    return {
      success: true,
      hello: 1
    };

预期结果:

//update status in database
    const userRef = db.collection("users").doc(uid);
    let updatedStatus = userRef.update({
      paid: true,
      last4: last4 //undefined
    });

    updatedStatus.catch(err => {
      console.log(err);
    });
    //send success message to client
    return {
      success: true,
      hello: 1

所有这些都在我获得last4的值之后运行。

1 个答案:

答案 0 :(得分:0)

您在这里错过了JS最重要的部分。 Javascript是异步的。因此,当您的代码正在执行这两个异步调用时,您的userRef.update()也同时被调用。这就是为什么您变得不确定。而且,如果这一切都发生在函数内部,那么您的回报并不会真正为您提供帮助。由于它异步工作,因此总是会返回成功。

查看以下代码。您需要返回一个Promise,以便您的函数等待所有异步函数返回响应。

yourFunction() {
return new Promise ( function(resolve, reject) {
if (intent.status === "succeeded") {
    const user = res.locals.decodedClaims;
    const uid = user.uid;
    let last4; //trying to set last4 to global var so that i can change it inside a function

    // The payment didn’t need any additional actions and completed!
    // Handle post-payment fulfillment

    //get payment last4 digits
    stripe.paymentIntents.retrieve(intent.id, function(err, paymentIntent) {
      // asynchronously called
      if (err) {
        reject(err);
     }
      stripe.charges.retrieve(paymentIntent.charges.data[0].id, function(
        err,
        charge
      ) {
        if (err) {
          reject(err);
        }
        last4 = charge.payment_method_details.card.last4;
        console.log("charge: ", last4); // works, eg: 4242
        //update status in database
        const userRef = db.collection("users").doc(uid);
        let updatedStatus = userRef.update({
          paid: true,
          last4: last4 //undefined
        });

        updatedStatus.catch(err => {
          reject(err);
        });
        //send success message to client
        resolve({
          success: true,
          hello: 1
        });
      });
    });


});

此后,您可以像这样调用函数

myFunction().then(function(success) {
   // your {success: true, hello: 1} comes here
}).catch(function(err)) {
   // all the errors come here.
}

如果要改为使用异步/等待,则只需定义您的主函数,使其async functionName() {}。 然后,执行以下操作:

try {
  selectedPlan = await Stripe.plans.retrieve(stripePlanId); // use stripe's functions here.
} catch (error) {
  // error handling
}