En este módulo, aprenderemos cómo manejar errores en GraphQL de manera efectiva. El manejo adecuado de errores es crucial para proporcionar una buena experiencia de usuario y para mantener la integridad y seguridad de nuestras aplicaciones.

Conceptos Clave

  1. Tipos de Errores en GraphQL:

    • Errores de Sintaxis: Ocurren cuando la consulta no sigue la sintaxis correcta de GraphQL.
    • Errores de Validación: Suceden cuando la consulta es sintácticamente correcta pero no válida según el esquema.
    • Errores de Ejecución: Se producen durante la ejecución de la consulta, como errores de lógica en los resolvers o problemas de conexión a la base de datos.
  2. Estructura de Errores en GraphQL:

    • Los errores en GraphQL se devuelven en un campo errors en la respuesta.
    • Cada error tiene un mensaje y puede incluir información adicional como el camino (path) y las ubicaciones (locations) en la consulta.

Ejemplo Práctico

Configuración Básica de Errores

Vamos a configurar un servidor GraphQL básico y agregar manejo de errores.

Paso 1: Configuración del Servidor

const { ApolloServer, gql } = require('apollo-server');

// Definición del esquema
const typeDefs = gql`
  type Query {
    hello: String
  }
`;

// Implementación de los resolvers
const resolvers = {
  Query: {
    hello: () => {
      throw new Error('Este es un error de ejemplo');
    },
  },
};

// Creación del servidor
const server = new ApolloServer({ typeDefs, resolvers });

// Inicio del servidor
server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});

En este ejemplo, el resolver para hello lanza un error intencionalmente.

Paso 2: Ejecución de la Consulta

Al ejecutar la consulta:

query {
  hello
}

La respuesta será:

{
  "errors": [
    {
      "message": "Este es un error de ejemplo",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "hello"
      ]
    }
  ],
  "data": {
    "hello": null
  }
}

Manejo de Errores en Resolvers

Podemos manejar errores de manera más específica en los resolvers.

Ejemplo de Resolver con Manejo de Errores

const resolvers = {
  Query: {
    hello: () => {
      try {
        // Lógica que puede lanzar un error
        throw new Error('Este es un error de ejemplo');
      } catch (error) {
        // Manejo del error
        return new Error('Error manejado: ' + error.message);
      }
    },
  },
};

Personalización de Errores

Podemos personalizar los errores para proporcionar más contexto.

Ejemplo de Error Personalizado

class UserInputError extends Error {
  constructor(message, properties) {
    super(message);
    this.name = 'UserInputError';
    Object.assign(this, properties);
  }
}

const resolvers = {
  Query: {
    hello: () => {
      throw new UserInputError('Error de entrada del usuario', {
        invalidArgs: ['name'],
      });
    },
  },
};

La respuesta será:

{
  "errors": [
    {
      "message": "Error de entrada del usuario",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "hello"
      ],
      "extensions": {
        "invalidArgs": [
          "name"
        ]
      }
    }
  ],
  "data": {
    "hello": null
  }
}

Ejercicio Práctico

Ejercicio 1: Manejo de Errores en Mutaciones

  1. Objetivo: Implementar una mutación que maneje errores de validación.
  2. Descripción: Crear una mutación createUser que valide la entrada y maneje errores de validación.

Paso 1: Definición del Esquema

type Mutation {
  createUser(name: String!, age: Int!): User
}

type User {
  id: ID!
  name: String!
  age: Int!
}

Paso 2: Implementación del Resolver

const resolvers = {
  Mutation: {
    createUser: (_, { name, age }) => {
      if (age < 0) {
        throw new UserInputError('La edad no puede ser negativa', {
          invalidArgs: ['age'],
        });
      }
      // Lógica para crear el usuario
      return {
        id: '1',
        name,
        age,
      };
    },
  },
};

Solución del Ejercicio

Al ejecutar la mutación:

mutation {
  createUser(name: "John", age: -1) {
    id
    name
    age
  }
}

La respuesta será:

{
  "errors": [
    {
      "message": "La edad no puede ser negativa",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "createUser"
      ],
      "extensions": {
        "invalidArgs": [
          "age"
        ]
      }
    }
  ],
  "data": {
    "createUser": null
  }
}

Conclusión

En esta sección, hemos aprendido cómo manejar errores en GraphQL de manera efectiva. Hemos cubierto los tipos de errores, cómo se estructuran en las respuestas de GraphQL y cómo personalizar y manejar errores en los resolvers. El manejo adecuado de errores es esencial para construir aplicaciones robustas y proporcionar una buena experiencia de usuario.

En el próximo módulo, exploraremos técnicas avanzadas para optimizar el rendimiento de nuestras consultas GraphQL.

© Copyright 2024. Todos los derechos reservados