Graphql resolvers
Graphql resolvers
- Resolvers within GraphQL are functions that produce the values for each field defined in a type/struct
- GraphQL servers always have a “root field”, which is the entry point into that particular interface (known as the “root type” or “query type”)
- Example:
Query: {
human(obj, args, context, info) {
return context.db.loadHumanByID(args.id).then(
userData => new Human(userData)
)
}
}
- This query type provides a field called
human
- the resolver function queries the database to fetch a
human
by the id
argument
- Resolvers are basically just functions that query the database for a value to assign to the particular field they’re assigned to
- Resolver functions accept 4 arguments:
obj
- the previous object (likely not used on the root query type)
args
- the arguments provided to the field in the GraphQL query
context
- the context of the current operation (may contain the current user or database credentials)
info
- information relevant to the current query (schema details, etc. ↗)
- Types of resolvers:
- asynchronous:
- resolver functions are often asynchronous (and need to be written as such) since they request asynchronous data (from remote databases, etc.)
- GraphQL automatically waits for asynchronous resolvers, no extra configuration necessary
- trivial:
- sometimes a GraphQL query is just looking for a the value of a particular key on the current object
- e.g.:
Human: {
name(obj, args, context, info) {
return obj.name
}
}
- this is very straight forward since it just involves returning the value for the key requested, which happens to be the name of the resolver
- scalar coercion:
- type system is “smart” and can convert unexpected values into types that fulfill the data contract, if possible, such as converting a list to an Enum (specifies a type for its values)
- list resolvers:
- what if a resolver returns a list of Promises, rather than just a single Promise?
- GraphQL waits for the Promises concurrently and resolves each one’s results, so values can be resolved into lists within the resolver function itself
- Finishing the execution and getting a result:
- each field is resolved according to its function, with the results being assigned into a key-value map which is the final resulting structure