Joris
Joris

Reputation: 777

onCall Cloud Function don't wait for promise to finish

I have a function who is always finishing before returning results. I tried many solutions I found on stackoverflow but none of theme seems to work. Here is my last try. Can you see where the error is ?

exports.myFunction = functions.https.onCall((data, context) => {
  if (!context.auth.uid) {
    return {
      status: "NOK",
    };
  }
  Promise.all(
    stripe.paymentMethods.attach(data.pm, { customer: data.cust }, function (err, paymentMethod) {
      if (err) {
        return {
          status: "NOK",
        };
      }
      Promise.all([
        FIRESTORE.collection("Users")
          .doc(context.auth.uid)
          .collection("PM")
          .doc(paymentMethod.id)
          .set(paymentMethod),

        FIRESTORE.collection("Users")
          .doc(context.auth.uid)
          .update({ pm: paymentMethod.id }),
      ])
      return { status: "OK" }
    })
  )
})

In my returned data I should have "status" defined but I only get data: null

Upvotes: 0

Views: 346

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598658

You need to return a promise from the top-level code of your function to the Cloud Functions environment. Otherwise it has no way to know what it's supposed to wait for.

In addition you need to bubble up the promises from any nested asynchronous operations.

Finally: if the Stripe API doesn't return a promise, you'll need to convert its results to a promise yourself. But from my reading of their API docs, it seems to return a promise, so you'll also need to chain that with the other promises.

So:

exports.myFunction = functions.https.onCall((data, context) => {
  if (!context.auth.uid) {
    return {
      status: "NOK",
    };
  }
  return Promise.all(
    return stripe.paymentMethods.attach(data.pm, { customer: data.cust })
    .then(function(paymentMethod) {
      return Promise.all([
        FIRESTORE.collection("Users")
          .doc(context.auth.uid)
          .collection("PM")
          .doc(paymentMethod.id)
          .set(paymentMethod),

        FIRESTORE.collection("Users")
          .doc(context.auth.uid)
          .update({ pm: paymentMethod.id }),
      ]).then(function() {
        return { status: "OK" }
      });
    })
    .catch(function(err) {
      if (err) {
        return {
          status: "NOK",
        };
      }
    });
  )
})

I highly recommend studying how promises work before continuing to use them in Cloud Functions, as your code seems based on an incomplete and incorrect understanding.

Upvotes: 2

Related Questions