简体   繁体   中英

Chaining Asynchronous Function Calls with Stripe and Axios in React

So I try to submit an order for which the user entered his/her credit card.

To do so, I call the order method that make an API call to Stripe ( createSource ) to create a payment source. Then I post the order parameters to my Rails backend using axios, in which I send the id of the source that was just created ( source.id ).

async order() {
      let {source} = await this.props.stripe.createSource({type: 'card', currency: 'eur', owner: {email: this.props.currentUserEmail}});
      axios.post("/orders", {sourceId: source.id,
                              mealId: this.props.mealId,
                              price: this.state.mealPrice,

                              selectedPickupTime: this.state.selectedPickupTime
                            })
}

The problem is, I think the source isn't yet created when axios send the post request to the backend, as I get the following error:

Unhandled Rejection (TypeError): Cannot read property 'id' of undefined for source.id

How can I change that and wait for source to be created before axios sends the post request ?

There might be an error when creating a source. According to stripe docs you need to check if the request were successful this way.

async order() {
      // Either Source or Error
      let {source, error} = await this.props.stripe.createSource({type: 'card', currency: 'eur', owner: {email: this.props.currentUserEmail}});

      if (error) { // there was an error
        console.error('Unable to create a source due to', error) 
      } else {
        axios.post("/orders", {sourceId: source.id,
                              mealId: this.props.mealId,
                              price: this.state.mealPrice,

                              selectedPickupTime: this.state.selectedPickupTime
                            })
     }
}

From the docs , it looks like the correct way to do this is:

class CheckoutForm extends React.Component {
  handleSubmit = (ev) => {
    // We don't want to let default form submission happen here, which would refresh the page.
    ev.preventDefault();
    this.props.stripe.createSource({type: 'card', currency: 'eur', owner: {email: this.props.currentUserEmail}})
      .then(source => axios.post("/orders", {sourceId: source.id, mealId: this.props.mealId, price: this.state.mealPrice, selectedPickupTime: this.state.selectedPickupTime }))
      .catch(err => console.log(err));

  }
};

In your case, there's an error from the async function. Use try-catch for your implementation in order to handle promise rejection.

async order() {
  try {
    let source = await this.props.stripe.createSource({ type: 'card', currency: 'eur', owner: { email: this.props.currentUserEmail }});
    axios.post("/orders", {
      sourceId: source.id,
      mealId: this.props.mealId,
      price: this.state.mealPrice,
      selectedPickupTime: this.state.selectedPickupTime
    });
  }
  catch (err) { // there was an error
    console.error('Unable to create a source due to', error)
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM