Resolvers are a critical part of a GraphQL server. They are responsible for fetching the data for each field in a query. In this section, we will cover the following topics:
- What are Resolvers?
- How Resolvers Work
- Writing Basic Resolvers
- Resolver Arguments
- Context in Resolvers
- Practical Examples
- Exercises
- What are Resolvers?
Resolvers are functions that handle the logic for fetching the data for a specific field in a GraphQL query. They are the bridge between the schema and the data sources.
- How Resolvers Work
When a GraphQL query is executed, the server maps each field in the query to a resolver function. The resolver function then fetches the data and returns it to the client.
Example:
Consider the following GraphQL query:
For this query, the server will use resolvers to fetch the user
data and then the name
and email
fields of that user.
- Writing Basic Resolvers
Let's start by writing a basic resolver for a simple schema.
Schema Definition:
Resolver Function:
In this example, the hello
field in the Query
type is resolved by the hello
function, which returns the string "Hello, world!".
- Resolver Arguments
Resolvers can accept four arguments:
- parent: The result of the previous resolver in the chain.
- args: An object containing the arguments passed to the field.
- context: An object shared by all resolvers in a GraphQL operation.
- info: Information about the execution state of the query.
Example:
Consider the following schema:
Resolver Function:
const users = [ { id: '1', name: 'John Doe', email: '[email protected]' }, { id: '2', name: 'Jane Doe', email: '[email protected]' }, ]; const resolvers = { Query: { user: (parent, args, context, info) => { return users.find(user => user.id === args.id); }, }, };
In this example, the user
resolver uses the args
argument to find and return the user with the specified id
.
- Context in Resolvers
The context
argument is useful for sharing data across all resolvers, such as authentication information, database connections, or other utilities.
Example:
const resolvers = { Query: { user: (parent, args, context, info) => { if (!context.user) { throw new Error('Not authenticated'); } return context.db.users.find(user => user.id === args.id); }, }, };
In this example, the context
object contains the authenticated user and the database connection.
- Practical Examples
Example 1: Fetching Data from a Database
const resolvers = { Query: { user: async (parent, args, context, info) => { return await context.db.collection('users').findOne({ id: args.id }); }, }, };
Example 2: Using External APIs
const fetch = require('node-fetch'); const resolvers = { Query: { weather: async (parent, args, context, info) => { const response = await fetch(`https://api.weather.com/v3/wx/conditions/current?apiKey=${context.apiKey}&format=json`); return await response.json(); }, }, };
- Exercises
Exercise 1: Basic Resolver
Task: Write a resolver for the following schema that returns a greeting message.
Solution:
Exercise 2: Resolver with Context
Task: Write a resolver that fetches a user's profile only if the user is authenticated.
Solution:
const resolvers = { Query: { profile: (parent, args, context) => { if (!context.user) { throw new Error('Not authenticated'); } return context.db.users.find(user => user.id === context.user.id); }, }, };
Conclusion
In this section, we learned about resolvers, how they work, and how to write basic and advanced resolvers. We also covered how to use arguments and context in resolvers. With this knowledge, you are now equipped to handle data fetching in your GraphQL server. In the next section, we will dive into GraphQL types and how to define them in your schema.