The premature return of null in GraphQL mutation while integrating Stripe and MongoDB

I am facing an issue with my GraphQL mutation while trying to charge the user using Stripe. The payment is successfully processed on the server side and reflects in the database, but I am having trouble getting the updated user data back on the client side. The problem seems to be that the .then() function is triggering prematurely, resulting in a null response instead of the expected edited user information. It appears to be firing before the stripe.charges operation completes on the server.

Server-side :

chargeUser(args) {
    const { userId, membershipId, stripeToken } = args;

    return User.findById(userId)
        .then((user) => {
            return Membership.findById(membershipId)
                .then((membership) => {
                    return stripe.charges.create({
                        amount: membership.price * 100,
                        currency: 'chf',
                        source: stripeToken,
                        description: `${user.firstname} ${user.lastname}`
                    }, function(err) {
                        if (!err) {
                            user.membership = membershipId;
                            return user.save();
                        } else {
                            console.log(err)
                        }
                    });
                })
        });
}

Client-side :

this.props.mutate({
    variables: {
        membershipId: this.props.membershipId,
        userId: global.userId,
        stripeToken: token.tokenId
    }
})
.then((res) => {
    // Returning null before the stripe.charges has finished
    console.log(res)
})

Answer №1

This issue arises from the fact that stripe.charges.create() uses a callback function instead of returning a promise. When the callback is invoked, it does not affect the overall promise chain operation. Essentially, the promise chain ends at the return value of stripe.charges.create(), which is null.

To ensure that your resolver waits for the callback to complete, you must encapsulate it in a promise as demonstrated below:

return User.findUserById(userId)
  .then((user) => {
    return Membership.findMembershipById(membershipId)
      .then((membership) => {
        return new Promise((resolve, reject) => {
          stripe.charges.create({
            amount: membership.price * 100,
            currency: 'usd',
            source: creditCardToken,
            description: `${user.firstName} ${user.lastName}`
          }, (error) => {
            error ? reject(error) : resolve()
          })
        })
      })
      .then(() => user.save())
  })

Alternatively, you can optimize this code using async/await syntax:

const processPayment = async (args) => {
    const { userId, membershipId, creditCardToken } = args;

    const user = await User.findUserById(userId);
    const membership = await Membership.findMembershipById(membershipId);

    await new Promise((resolve, reject) => {
      stripe.charges.create({
        amount: membership.price * 100,
        currency: 'usd',
        source: creditCardToken,
        description: `${user.firstName} ${user.lastName}`
      }, (error) => {
        error ? reject(error) : resolve()
      });
    });

    return user.save();
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transforming a REST API get call into GraphQL

I'm currently using a REST API that accepts a code parameter, searches the database for matches, returns results if the parameter exists, and redirects users to a long_url retrieved from the database. How can I convert this functionality to GraphQL? i ...

Tips for showcasing data in the autocomplete feature

I have implemented the following code to show values: function retrieveValues(input) { var xhttp; if (input.length == 0) { document.getElementById("output").innerHTML = ""; return; } xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = functi ...

A Guide on Loading Environment Data for app.modules.ts in Angular

I am looking to retrieve data from a service that includes environment details. Specifically, I need certain data for a module within app.modules. Below is an example from app.modules.ts: import { CustomEnvironmentService } from './CustomEnvironment ...

How can I target the first checkbox within a table row using jQuery?

I am seeking a way to determine if the first checkbox in a table row is selected, rather than checking all checkboxes within that particular row. Currently, I am using this code: var b = false; $j('#tb1 td input:checkbox').each(function(){ ...

The Angular ViewportScroller feature appears to be malfunctioning in the latest release of Angular,

TestComponent.ts export class TestComponent implements OnInit, AfterViewInit { constructor( private scroller: ViewportScroller, ) {} scrollToAnchor() { this.scroller.scrollToAnchor('123456789'); } } HTM ...

Clicking on an Angular mat-checkbox requires two clicks to toggle between checked and unchecked states

My checkboxes are populating dynamically, but I am facing an issue when trying to unselect them. It takes two clicks to uncheck the checkbox. enter code here <mat-tree [dataSource]="dataSource" [treeControl]="treeControl"> ...

Reactive property cannot be defined on an undefined, null, or primitive value within the context of Bootstrap Vue modal

Can someone please assist me with this error message? It says "app.js:108639 [Vue warn]: Cannot set reactive property on undefined, null, or primitive value." I encountered this error while working with a Bootstrap Vue modal. Here is a snippet of my code: ...

Leveraging personalized AngularJS directives in conjunction with ExpressJS routing

I built my own AngularJS application following a tutorial at . However, I encountered an issue when trying to integrate it with an ExpressJS/Node backend. The tutorial only covers a single view with a single controller, while my Angular app includes multip ...

Matching current URL and links by checking the div class

How can I verify if the current URL matches a link on my page, but also check if that link has a specific div class? For example: jQuery(document).ready(function($){ // find anchor tag on page with matching current location URL jQuery("*").find("a[h ...

Communication between nodes using serial ports in Node.js fails to receive a response from the connected Arduino board

I've been attempting to establish communication between a computer and an Arduino board using node.js. Despite having a simple program, it just doesn't seem to work as expected. The Arduino program (which seems to be working fine) is as follows: ...

How to verify the presence of a value within a nested array in MongoDB

In one of my database collections, there is a field that consists of three arrays structured like this: use_homepage: { home: [Array], hidden: [Array], archive: [Array] } This particular field represents the homepage configuration for a user. ...

Exploring a collection of objects housed in a json document

Currently, I'm looking to retrieve a collection of objects using JavaScript from a JSON file that resides on my website. While I could easily embed the array of objects directly into my JavaScript code, I am interested in understanding how to work wit ...

How can I prevent the content from being pushed when the sidebar is opened in JavaScript and CSS? I want to make it independent

I'm struggling with making the sidebar independent of the main content when it's opened. I've included the CSS and JavaScript code below. Can someone provide assistance with this? function ExpandDrawer() { const drawerContent = docu ...

Are you struggling with Grails - Ajax submission not functioning properly?

Trying to update a div when a form is submitted, but it seems like something is missing. Here's the HTML code: <%@ page contentType="text/html;charset=UTF-8" %> <html> <head> <meta name="layout" content="main" /> ...

The JavaScript modal popup feature functions perfectly in CodePen but fails to work properly on the

I have been experimenting with a responsive modal popup window that can handle HTML text and HTML5 videos. It seems to work perfectly fine on CodePen, as you can see here: https://codepen.io/jabbamonkey/pen/NYdZXq However, when I try to integrate it into ...

Is there a way to instantly remove script from the document head using jQuery instead of waiting a few seconds?

I currently have a setup where I am utilizing Google Maps in production. To make this work, I must include a script in the head of my document that contains the API key for the Google Maps JavaScript API that my application relies on. The API key is being ...

Why is the imported package not being recognized in the namespace declaration of my Node.js TypeScript file?

Currently, I am utilizing the WebStorm IDE developed by JetBrains to modify a TypeScript file within a Node.js v8.6.0 project. The JavaScript version set for this project is JSX Harmony. In the beginning of the TypeScript source file, there is an import st ...

What are the specific files I should modify for HTML/CSS in my Ruby application?

My application was initially created with an introduction from: http://guides.rubyonrails.org/getting_started.html I am now looking to add some color and style through CSS. I have located the JavaScript and CSS files, but I am unsure which file is respons ...

When I hover over the button, the Fontawesome arrow will shift its position

.b_btnWrapp .btn.btn_default:after { content: "\f054"; font-family: 'Font Awesome 5 Free'; font-weight: 900; position: absolute; top: 15px; right: 30px; } .b_btnWrapp .btn.btn_default:after:hover { content: "\f054"; fon ...

Retrieve complete browsing history using asp.net

Similar Question: How can browser history be accessed? I am interested in obtaining a list of websites visited by the client through their browser history in order to gather information from these sites and display it on my website. How can I access t ...