10

I am studying GraphQL and I get a bit confused from different implementations on the specific issue when writing the fields of a GraphQLObjectType.
What is the difference between these two implementations?

1.

var schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {  // as object
      echo: {
        type: GraphQLString,
        args: {
          email: { type: EmailType }
        },
        resolve: (root, {email}) => {
          return email;
        }
      }
    }
  })
});
var ComplicatedArgs = new GraphQLObjectType({
  name: 'ComplicatedArgs',
  fields: () => ({ // as function
    complexArgField: {
      type: GraphQLString,
      args: {
        complexArg: { type: ComplexInput }
      },
    }
  }),
});
Yilmaz
  • 35,338
  • 10
  • 157
  • 202
itaied
  • 6,827
  • 13
  • 51
  • 86
  • What difference in particular do you refer to? The first snippet creates a whole schema with a query type and a resolvable `echo` field, the second snippet only creates an object type with a `complexArgField` field and no resolver. – Bergi Jan 08 '22 at 07:40

2 Answers2

6

When you need to make a circular reference.

Look for my similiar answer here

Dynamically creating graphql schema with circular references

Community
  • 1
  • 1
LordDave
  • 1,118
  • 1
  • 11
  • 22
6

This is a great example of CLOSURE. Imagine you have two types in a file and they are referencing each other.

const BookType= new GraphQLObjectType({
    name: 'BookType',
    fields: {  // as object
      author: {
        type: AuthorType,
        
        resolve: (parentValue, args) => {
          // query the author based on your db implementation.
        }
      } }
  })

BookType has a field author and referencing AuthorType. Now imagine you have AuthorType defined under "BookType" referencing BookType

const AuthorType= new GraphQLObjectType({
    name: 'AuthorType',
    fields: {  // as object
      books: {
        type: new GraphQLList(BookType), //one author might have multiple books
        
        resolve: (parentValue, args) => {
          // query the books based on your db implementation.
        }
      } }
  })

So when Javascript engine needs to use BookType it will see that fields.author.type is AuthorType and AuthorType is not defined above. So it will give

reference error:AuthorType is not defined

to circumvent this, we turn fields to a function. this function is a CLOSURE function. this is a great example why closures are so helpful.

When js engine reads the file first, it saves all the variables that are referenced inside of a function into memory heap as a closure storage of that function. All the variables that BookType.fields need are stored into the closure environment of the BookType.fields(). So now if javascript executes the Booktype.fields(), it checks if "AuthorType" is defined inside the function, it is not defined so it checks its closure storage, AuthorType was already stored there in the beginning, so it uses it.

Yilmaz
  • 35,338
  • 10
  • 157
  • 202