Table des matières

Avantages de l'utilisation de GraphQL par rapport aux API REST

L'un des problèmes les plus courants avec REST est celui de l'extraction excessive ou insuffisante de données. Ces problèmes surviennent parce que la seule façon pour un client de télécharger des données est d'atteindre des points d'extrémité qui renvoient des structures de données fixes. Il est difficile de concevoir l'API de manière à ce qu'elle puisse fournir aux clients les données dont ils ont exactement besoin.

  • GraphQL réduit les requêtes réseau en nous permettant de récupérer toutes les données dont nous avons besoin en une seule requête.
  • Avec GraphQL, il n'y a pas besoin de versionner, car nous pouvons facilement ajouter de nouveaux champs et de nouveaux types à notre API GraphQL sans affecter les requêtes existantes. De plus, nous pouvons facilement marquer des champs comme étant obsolètes, et ces champs seront exclus de la réponse reçue du serveur.
  • Avec GraphQL, vous pouvez également effectuer un contrôle de bas niveau des performances des requêtes traitées par votre serveur. GraphQL utilise le concept de fonctions de résolution pour collecter les données demandées par un client. L'instrumentation et la mesure des performances de ces résolveurs permettent d'obtenir des informations cruciales sur les goulets d'étranglement de votre système.

Brève explication du fonctionnement de GraphQL

La mise en œuvre de GraphQL comprend principalement trois parties

  • Schéma - Décrit les données.
  • Résolveurs - Logique d'extraction des données à partir de différentes ressources (microservices).
  • Requête - Le client demande quelles données doivent être récupérées.

Schéma(En savoir plus sur le schéma et les types)

➡️
type Query{getUsers:[User]getUser(user_id:Int!):User}type Mutation{addUser(first_name:String!,last_name:String,pic:String):Boolean deleteUser(user_id:Int!):Boolean}type User{first_name:Stringlast_name:Stringpic:Stringfull_name:Stringuser_id:Int!designation:String}

Le code ci-dessus décrit ce qui peut être interrogé et les données de réponse (type de données) attendues des ressources.

P.S. : "!" signifie que le champ ne peut pas être nul ou indéfini.

Résolveurs (le code ci-dessous est écrit en NodeJs)

➡️
{Query:{getUsers:(obj,args,context,info) => { return users},getUser:(obj,{user_id},context,info) => { return users.find(user => user.user_id == user_id) } },Mutation:{ addUser:(obj,{first_name,last_name,pic},context,info) => { users.push({ first_name:first_name, last_name:last_name, pic:pic }) return true },deleteUser:(obj,{user_id},context,info) => { for (var i = 0; i < users.length; i++) { if(users[i].user_id == user_id){ users.splice(i,1) return true }}return false } }, User:{ full_name:(prev_obj,args,context,info) => { return `${prev_obj.first_name} ${prev_obj.last_name}`}}}

Le code ci-dessus décrit la logique qui est exécutée lorsque le client fait une demande.

P.S. J'ai utilisé la fonction de résolution du nom complet pour le type d'utilisateur afin d'écrire ma propre logique.

Requête(En savoir plus sur la requête)

➡️
{getUsers{full_name pic}}

Leclient effectue une requête en utilisant le code ci-dessus qui renvoie uniquement le nom complet et l'image comme ci-dessous.

P.S. Le client ne peut interroger que les champs définis dans le schéma.

➡️
{"data":{"getUsers":{"full_name":"Srinivasa Sainath", "pic":"https://vpms.xoxoday.com/images/xoxoday.png"}}}

La requête du client peut être de type Requête et Mutation ( et Abonnement. Ceci sera discuté dans les prochains blogs de la série GraphQL).

Les deux requêtes font la même chose. Sauf que la Mutation est exécutée de manière synchrone . La convention qui est suivie est que la Mutation est utilisée pour toute opération qui provoque des écritures dans le serveur (mise à jour du profil, création d'une commande, etc.) et qu'une requête est utilisée pour récupérer des données (obtenir le menu, obtenir la liste des bons, etc.). (Semblable à GET et POST). Techniquement, les deux types de requêtes peuvent être utilisés pour exécuter n'importe quelle logique. Mais il est préférable de suivre la convention pour aider votre équipe.

Points importants pour comprendre la relation entre les fonctions du résolveur et la requête

  • Vous pouvez considérer chaque champ d'une requête GraphQL comme une fonction ou une méthode du type précédent qui renvoie le type suivant. C'est précisément ainsi que fonctionne GraphQL. Chaque champ de chaque type est soutenu par une fonction appelée résolveur, fournie par le développeur du serveur GraphQL. Le résolveur correspondant est appelé pour produire la valeur suivante lorsqu'un champ est exécuté.
  • L'exécution s'achève si un champ produit une valeur scalaire telle qu'une chaîne de caractères ou un nombre. Cependant, si un champ a une valeur d'objet, la requête contiendra une autre sélection de champs qui s'appliquent à cet objet. Cette opération se poursuit jusqu'à ce que les valeurs scalaires soient atteintes. Les requêtes GraphQL se terminent toujours à des valeurs scalaires.

Une fonction de résolution reçoit quatre arguments

Syntaxe :

➡️
{getUsers:(obj,args,context,info) =>{ return users }}
  • obj L'objet précédent, qui pour un champ sur le type de requête racine n'est souvent pas utilisé.
    Pour en savoir plus sur cet argument, consultez GraphQL Server With Node.js.
  • args Les arguments fournis au champ dans la requête GraphQL. Dans la fonction de résolution ci-dessus, {user_input} est l'argument.
  • context Valeur fournie à chaque résolveur et contenant des informations contextuelles importantes telles que l'utilisateur actuellement connecté ou l'accès à une base de données. Dans le résolveur ci-dessus, la fonction context est utilisée pour passer token_info
  • info Une valeur qui contient des informations spécifiques au champ, pertinentes pour la requête en cours, ainsi que les détails du schéma. Souvent non utilisée
➡️
Clone the demo GraphQL project from here.P.S. In the next part of the GraphQL series, I will discuss how to implement GraphQL as an API Gateway.
Srinivasa Sainath

Srinivasa Sainath