web-dev-qa-db-fra.com

Comment gérer les erreurs et envoyer une réponse dans GraphQL

Je commençais avec GraphQL et je ne pouvais pas comprendre comment nous pouvons lancer des erreurs dans GraphQL

J'ai parcouru quelques articles sur le Web, mais presque tous utilisent Apollo et la structure du code est très différente de la façon dont je travaille.

Considérez ce morceau de code, ici où je fais une mutation, maintenant comment envoyer un message de réponse avec erreur et changer le message d'état des en-têtes en cas d'erreur?

  AddNewPersonalInfo: {
  type: userDashboardType,
  args: { 
    parameter: {
      type: userCreationlInputType
    }
  }, 
  resolve: async (parent, args, context) => {
    args.parameter.userId = context.req.headers.userId
    //Check if user info already exsist
    const checkIfUserInformationExsist = await getSelectedThingFromTable('CatsWork_personal', 'userId', `${userId}`)
    if (checkIfUserInformationExsist[0]) {
      const error = {
        code: 403, 
        message: 'User info Already exsist'
      }
      throw new Error(error)
    } else {
      try {
      const addLinkedinUser = await insertIntheTable('personal', payload)
      return true
      } catch (err) {
        console.error(err)
        throw new Error(err)
      }
    }
  }
}
10
anny123

Ce que j'ai rencontré dans l'un de mes projets, il est difficile de définir le code d'état de la réponse. Donc, j'ai fait une réponse d'erreur personnalisée pour identifier le statusCode correct en utilisant express-graphql

Voici l'exemple ( Ce que j'ai utilisé dans l'un de mes projets):

--------app.js file--------

const graphqlHTTP = require('express-graphql')

app.use('/graphql', (req, res) => {
  graphqlHTTP({
    schema: GraphQLSchema, //A GraphQLSchema instance from GraphQL.js. A schema must be provided.
    graphiql: true,
    context: { req },
    formatError: (err) => {
      const error = getErrorCode(err.message)
      return ({ message: error.message, statusCode: error.statusCode })
    }
  })(req, res)
})

--------getErrorCode implémentation de la fonction --------

const { errorType } = require('../constants')

const getErrorCode = errorName => {
  return errorType[errorName]
}

module.exports = getErrorCode

--------Constant.js fichier --------

exports.errorName = {
  USER_ALREADY_EXISTS: 'USER_ALREADY_EXISTS',
  SERVER_ERROR: 'SERVER_ERROR'
}

exports.errorType = {
  USER_ALREADY_EXISTS: {
    message: 'User is already exists.',
    statusCode: 403
  },
  SERVER_ERROR: {
    message: 'Server error.',
    statusCode: 500
  }
}

Maintenant, nous sommes prêts à utiliser notre configuration.

À partir de votre requête ou mutation, vous devez exiger un fichier constant et renvoyer une erreur personnalisée:

const { errorName } = require('../constant')

AddNewPersonalInfo: {
  type: userDashboardType,
  args: { 
    parameter: {
      type: userCreationlInputType
    }
  }, 
  resolve: async (parent, args, context) => {
    args.parameter.userId = context.req.headers.userId
    //Check if user info already exsist
    const checkIfUserInformationExsist = await getSelectedThingFromTable('CatsWork_personal', 'userId', `${userId}`)
    if (checkIfUserInformationExsist[0]) {
      const error = {
        code: 403, 
        message: 'User info Already exsist'
      }
      throw new Error(errorName.USER_ALREADY_EXISTS) // Here you can use error from constatnt file
    } else {
      try {
      const addLinkedinUser = await insertIntheTable('personal', payload)
      return true
      } catch (err) {
        console.error(err)
        throw new Error(errorName.SERVER_ERROR) // Here you can use error from constatnt file
      }
    }
  }
}

-------- Réponse d'erreur --------

{
  error: [{
    "statusCode": 403,
    "message": "User is already exists."
  }],
  data: null
}

Nous avons juste besoin d'écrire la gestion des erreurs personnalisée du côté FS aussi).

Remarque:- formatError: est obsolète et remplacé par customFormatErrorFn. Il sera supprimé dans la version 1.0.0. Vous pouvez faire référence à customFormatErrorFn .

J'espère que cette aide!

2
Hardik Shah

graphql devrait être une couche de niveau application qui ne devrait pas (voir le dernier paragraphe pourquoi ne devrait pas et non ne nécessite pas ) http pour fonctionner. Bien que dans 99% des cas, il s'exécute au-dessus de http, en raison de sa commodité, graphql est lui-même un protocole de couche 7.

Qu'est-ce que cela signifie dans votre cas? Eh bien, cela signifie que vous ne devez pas mélanger les concepts de HTTP/REST avec les concepts de graphql et vous concentrer sur ce dernier. Le code d'erreur des en-têtes est un concept HTTP/REST, graphql envoie des erreurs dans le champ errors de la réponse et l'implémentation nodejs capture déjà toutes vos erreurs et les ajoute à la liste. Le statut HTTP sera toujours 200, et vos clients ne devraient pas se soucier et consommer votre API graphql et non un mélange de REST avec graphql.

Maintenant, cela étant dit, il y a quelques choses qui REST sur HTTP fait mieux. Donc, les gens, y compris les développeurs d'Apollo, ont un peu mélangé les concepts aussi, principalement parce que la norme graphql n'est pas complète ( aka, il n'a pas de norme/règle pour résoudre tous les problèmes que vous pourriez rencontrer lors de la construction d'une API), alors les gens ont improvisé. Honnêtement, je ne recommanderais pas encore graphql pour tout projet sérieux. vaut la peine. Restez avec REST sur HTTP.

Référence

2
Valentin Radu