1

I'm trying to glue GraphQL (Apollo/Node.js) and gRPC (Go) together. So far, I can communicate between them.

However, I can't return a created user value from gRPC client callback.

Here's the user schema;

// schema.ts

import {gql} from 'apollo-server-express'

const schema = gql`
  type Mutation {
    addUser(input: AddUser): User
  }

  type User {
    id: ID!
    email: String
  }

  input AddUser {
    email: String!
    password: String!
  }
`

export default schema

And this is the resolver;

// resolver.ts

import {add} from '../client'

const resolver = {
  Query: {
    users: () => console.log('in progress'),
  },
  Mutation: {
    // addUser: (_: any, {input}: any) => add(input),

    // This successfully logs the `res`
    // addUser: (_: any, {input}: any) => add(input, (res: any) => console.log('Logged from resolver >', res)),

    // This returns null in mutation
    addUser: (_: any, {input}: any) => add(input, (res: any) => {
      return res
    }),
  }
}

export default resolver

This is the gRPC client and it returns undefined.

// client.ts

export async function add(input: any) {

  // Confirmed created in database
  client.addUser({
    email: input.email,
    password: input.password
  }, (_err: any, res: any) => {

    // Successfully logs `res`
    console.log('Logged res here > ', res)

    return res
  })
}

Please help me.


Edit:

I also tried with callback function:

export async function add(input: Input, callback: any) {
  try {
    await client.addUser({
      email: input.email,
      password: input.password
    }, (_err: any, res: any) => {
      console.log('Logged res here > ', res)
      return callback(res)
    })
  } catch (error) {
    console.log(error);
  }
}

Still returns null in mutation:

    addUser: (_: any, {input}: any) => add(input, (res: any) => {
      return res
    }),
Swix
  • 1,883
  • 7
  • 33
  • 50
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – John Montgomery Jan 03 '20 at 18:41
  • @JohnMontgomery No, it doesn't. I tried to retrieve the `res` with a variable but got undefined. – Swix Jan 03 '20 at 18:55

1 Answers1

3

GraphQL resolvers should return a value of the appropriate type, or else a Promise that will resolve to that value. Callbacks and Promises are both ways to handle code asynchronously, but they are not compatible.

It's unclear what client library you're using, but most libraries that utilized callbacks now also expose a Promise API -- if yours does, you should use that. If that's not an option, you should wrap the callback with a Promise. Something like:

const resolver = {
  Mutation: {
    addUser: (_: any, {input}: any) => new Promise((resolve, reject) => {
      add(input, (res) => {
        resolve(res)
      })
    }),
  },
}

Note that if your callback is passed an error, you should make sure you call reject with the error instead of calling resolve.

Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183