Lección 3 de 20 · Lectura y práctica
Crear Resolvers Simples para Consultas
Tipo de lección: VideoConcepto claveLos resolvers son funciones que se ejecutan para obtener los datos solicitados en una consulta GraphQL. Piensa en ellos como los "camareros" de tu API: cuando un cliente (frontend) pide un.
Del concepto a la práctica
Taller de esta lección
Un resolver de consulta debe traducir argumentos a una selección determinista de datos. Para una búsqueda por identificador, la responsabilidad concreta es leer args.id, localizar un registro y devolver null si no existe; no debe ignorar el argumento ni devolver toda la colección.
Ejemplo resuelto
Con datos locales:
const rooms = [{ id: "r1", name: "Norte" }, { id: "r2", name: "Sur" }];
const resolvers = { Query: { room: (_p: unknown, { id }: { id: string }) => rooms.find(r => r.id === id) ?? null } };room(id: "r2") produce { "id": "r2", "name": "Sur" }.
Define el tipo
Roomy el camporoom(id: ID!): Room.Conserva los datos de prueba en una colección pequeña.
Extrae el identificador desde
args.Prueba un identificador existente y otro ausente.
Error frecuente: comparar parent.id en el resolver de Query.room. Corrección: el nivel raíz no tiene parent útil; el dato solicitado está en args.
Pruébalo
Agrega capacity: Int! y devuelve la capacidad de cada sala sin modificar la búsqueda.
Comprueba tu resultado
room(id: "r1") devuelve solo la sala Norte, el identificador desconocido devuelve null y pedir un campo inexistente falla durante la validación.
Define también el contrato de sala
Usa type Room { id: ID!, name: String!, capacity: Int! } y type Query { room(id: ID!): Room }; agrega capacity=4 para r1 y capacity=8 para r2 a los datos. Selecciona { room(id: "r2") { id name capacity } }: obtienes Sur y 8. No declares capacity no nulo antes de completar todos los registros. room(r9) devuelve null porque el campo raíz es nullable; la respuesta de un objeto inexistente no equivale a una operación con un campo desconocido.

Mapa de prácticaEl navegador envía una solicitud a la API. El servidor valida la operación y consulta los datos; después devuelve una respuesta que el navegador puede mostrar. La base de datos se comunica con el servidor y no directamente con el navegador.
Ver la infografía en tamaño completo ↗Fuentes para profundizar
Tipo de lección: Video
Concepto clave
Los resolvers son funciones que se ejecutan para obtener los datos solicitados en una consulta GraphQL. Piensa en ellos como los "camareros" de tu API: cuando un cliente (frontend) pide un plato específico (campo de datos), el camarero va a la cocina (base de datos, servicio externo, etc.) y trae exactamente lo que se solicitó.
En GraphQL con Apollo Server, cada campo definido en tu schema necesita un resolver correspondiente. La magia está en que GraphQL resuelve los campos de forma jerárquica: si consultas usuario { nombre posts { titulo } }, primero se ejecuta el resolver para usuario, luego para nombre (que suele ser simple), y finalmente para posts (que puede requerir otra llamada a base de datos).
Un resolver recibe cuatro argumentos:parent(datos del nivel superior),args(argumentos de la consulta),context(información compartida como autenticación), yinfo(detalles de la consulta).
Cómo funciona en la práctica
Imagina que tienes un schema GraphQL para una aplicación de blog. Primero, defines los tipos en tu schema:
type Post {
id: ID!
titulo: String!
contenido: String!
autor: Usuario!
}
type Usuario {
id: ID!
nombre: String!
email: String!
posts: [Post!]!
}
type Query {
posts: [Post!]!
usuario(id: ID!): Usuario
}Luego, implementas los resolvers. Aquí un ejemplo paso a paso:
- Crea un archivo
resolvers.jscon un objeto que mapee los tipos y queries. - Para el query
posts, define una función que devuelva datos (por ahora, datos simulados). - Para el campo
autorenPost, usa el argumentoparentpara acceder al ID del autor y buscar el usuario correspondiente.
Ejemplo de implementación:
const resolvers = {
Query: {
posts: () => {
// Simula datos de una base de datos
return [
{ id: '1', titulo: 'Aprendiendo GraphQL', contenido: '...', autorId: '101' },
{ id: '2', titulo: 'Next.js Tips', contenido: '...', autorId: '102' }
];
},
usuario: (parent, args, context, info) => {
const { id } = args;
// Busca usuario por ID (simulado)
return { id, nombre: 'Carlos', email: 'carlos@ejemplo.com' };
}
},
Post: {
autor: (parent) => {
// parent contiene los datos del post, como autorId
return { id: parent.autorId, nombre: 'Autor Simulado' };
}
}
};Caso de estudio
Vamos a aplicar esto a un escenario real: una API para un e-commerce con productos y categorías. Supón que tienes este schema:
type Producto {
id: ID!
nombre: String!
precio: Float!
categoria: Categoria!
}
type Categoria {
id: ID!
nombre: String!
productos: [Producto!]!
}
type Query {
productos: [Producto!]!
categoria(id: ID!): Categoria
}Implementa resolvers que:
- Para
Query.productos, devuelva una lista de productos desde una fuente de datos (en este caso, un array en memoria). - Para
Producto.categoria, use elparentpara buscar la categoría correspondiente por ID. - Para
Categoria.productos, filtre los productos por categoría ID.
Datos de ejemplo en una tabla:
| ID Producto | Nombre | Precio | Categoria ID |
|---|---|---|---|
| P1 | Laptop | 999.99 | C1 |
| P2 | Mouse | 25.50 | C2 |
| P3 | Teclado | 45.00 | C2 |
El resolver de Producto.categoria podría verse así:
Producto: {
categoria: (parent) => {
const categorias = [
{ id: 'C1', nombre: 'Electrónica' },
{ id: 'C2', nombre: 'Accesorios' }
];
return categorias.find(cat => cat.id === parent.categoriaId);
}
}Errores comunes
- Olvidar devolver el tipo correcto: Si tu schema define
String!y devuelves un número, Apollo Server lanzará un error. Siempre valida que los datos coincidan con el schema. - No manejar argumentos en resolvers: Al definir un query con argumentos (ej:
usuario(id: ID!)), asegúrate de acceder aargs.iden el resolver. Un error típico es usarparent.idpor confusión. - Resolver asíncrono sin await: Si tu resolver hace una llamada a una base de datos (como con Prisma o MongoDB), recuerda usar
async/awaito promesas. Olvidarlo puede devolverPromiseen lugar de los datos. - Ignorar el contexto: El
contextes ideal para compartir datos como conexiones a DB o información de autenticación. No inicializarlo puede llevar a código repetitivo o inseguro. - Sobrecargar resolvers con lógica compleja: Mantén los resolvers simples; delega la lógica de negocio a servicios o capas separadas para mejorar mantenibilidad.
Checklist de dominio
- Puedo explicar qué es un resolver y su rol en GraphQL usando una analogía simple.
- He implementado al menos un query con argumentos y su resolver correspondiente.
- Sé acceder y usar los cuatro argumentos (
parent,args,context,info) en un resolver. - Puedo conectar resolvers para campos anidados (ej:
usuario.posts). - He simulado datos en memoria y los he devuelto desde un resolver.
- Reconozco y evito errores comunes como tipos incorrectos o manejo asíncrono.
- Puedo integrar un resolver básico en un proyecto Next.js con Apollo Server.
Implementa Resolvers para una API de Biblioteca
En este ejercicio, crearás resolvers simples para una API GraphQL que gestiona libros y autores en una biblioteca. Sigue estos pasos:
- Configura un proyecto Next.js con Apollo Server (usa el boilerplate del módulo anterior).
- Define el siguiente schema GraphQL en tu archivo
schema.js:type Libro { id: ID! titulo: String! autor: Autor! año: Int! } type Autor { id: ID! nombre: String! libros: [Libro!]! } type Query { libros: [Libro!]! autor(id: ID!): Autor } - Crea un archivo
resolvers.jse implementa los resolvers para:Query.libros: Devuelve un array con al menos 3 libros simulados (ej: datos en memoria).Query.autor: Acepta un argumentoidy devuelve un autor simulado basado en ese ID.Libro.autor: Usa elparentpara buscar y devolver el autor correspondiente al libro.Autor.libros: Filtra y devuelve los libros escritos por ese autor.
- Integra los resolvers en tu Apollo Server y prueba las consultas en GraphQL Playground (ej:
{ libros { titulo autor { nombre } } }). - Asegúrate de que los tipos devueltos coincidan con el schema y maneja los argumentos correctamente.
Datos de ejemplo para empezar:
- Libros: [{ id: 'L1', titulo: 'Cien años de soledad', autorId: 'A1', año: 1967 }, { id: 'L2', titulo: 'Rayuela', autorId: 'A2', año: 1963 }]
- Autores: [{ id: 'A1', nombre: 'Gabriel García Márquez' }, { id: 'A2', nombre: 'Julio Cortázar' }]
Pistas
- Usa el argumento 'parent' en el resolver de Libro.autor para acceder a autorId y buscar en el array de autores.
- En Query.autor, el argumento 'id' está en args, no en parent. Asegúrate de extraerlo con const { id } = args.
- Para Autor.libros, puedes filtrar el array de libros comparando autorId con el id del autor desde parent.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.
Sigue con GraphQL Profesional con Next.js y Apollo Server: APIs Tipadas y Suscripciones
Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.
Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.