Live Coding : Introduction à Ajax

21 septembre 2019 - : Javascript jQuery API Live-Coding - : 0 commentaire - : 147

Visualisez les fichiers de cette série sur GitHub

Lors de l'utilisation d'API en ligne, il est fréquent de devoir interroger le serveur distant pour obtenir ou écrire des données.

Il s'agit alors de trouver un moyen de faire dialoguer deux systèmes complètement différents et potentiellement incompatibles entre eux.

Nous allons faire une introduction à l'utilisation d'ajax, qui permet d'interroger des API depuis javascript.

Pour cet article, nous utiliserons l'exemple de l'API REST traitée dans l'article "Live Coding : Créer une API REST".

Ajax, c'est quoi ?

Ajax est un acronyme signifiant "Asynchronous Javascript And Xml", littéralement Javascript et Xml asynchrones.

Il s'agit d'une technique permettant d'allier le javascript et le XML (à l'origine) pour permettre aux clients et aux serveurs de dialoquer de manière asynchrone, sans interrompre l'exécution du reste du code.

XMLHttpRequest

Ajax est basé sur l'utilisation de l'objet Javascript XMLHttpRequest, créé par Microsoft puis repris et standardisé par Mozilla.

Cet objet gère tous les aspects de la transaction et possède des évènements qui nous permettent de gérer les différentes étapes et erreurs éventuelles.

Instancier l'objet XMLHttpRequest

Pour instancier cet objet, il suffit de s'y prendre comme pour tout objet Javascript, comme ci-dessous

// Instanciation de l'objet
let req = new XMLHttpRequest();

Une fois cet objet instancié, nous aurons accès à ses propriétés et méthodes pour gérer notre transaction.

Les évènements

  • abort : déclenché quand une requête a été annulée
  • error : déclenché quand une erreur est survenue
  • load : déclenché quand la requête se termine avec succès
  • loadend : déclenché quand la requête est terminée, avec succès ou non
  • loadstart : déclenché quand la requête a commencé à charger les données
  • progress : déclenché périodiquement quand une requête reçoit des données
  • timeout : déclenché quand une requête se termine après expiration du temps d'attente

Méthodes principales

  • abort : déclenche l'abandon de la requête
  • open : Initialise la requête
  • send : Envoie la requête

Propriétés principales

  • readyState : Etat de la requête
    • 0 : non envoyée (open n'a pas encore été appelé)
    • 1 : ouvert, open a été appelé
    • 2 : Entêtes reçues, send a été appelé, les entêtes et le statut sont disponibles
    • 3 : En cours de chargement, données partielles reçues
    • 4 : Terminé
  • response : contient la réponse sous la forme définie par responseType
  • responseText : contient la réponse sous forme textuelle
  • responseType : contient le type de réponse
    • "" : vide
    • arraybuffer : contient des données binaires sous forme d'un tableau d'octets
    • blob : contient des données binaires sous forme d'un "fichier"
    • document : contient des données HTML ou XML
    • json : contient des données sous forme d'objet Javascript obtenu après traitement du json reçu
    • text : contient du texte
  • responseURL : URL utilisée dans la requête
  • responseXML : contient un document XML ou HTML si la réponse peut être convertie dans ce format
  • status : contient le statut de la réponse
  • statusText : contient le statut de la réponse sous forme textuelle
  • timeout : nombre de millisecondes avant que la requête expire

Envoyer une requête "synchrone"

Bien que déconseillée, il existe une méthode pour envoyer une requête en mode synchrone.

Celle-ci interrompra l'exécution du javascript en attendant que la requête soit totalement exécutée, ce qui impactera l'expérience de l'utilisateur, celui-ci ayant des temps d'attente.

Pour envoyer une requête e mode synchrone, nous mettrons le 3ème paramètre de la méthode "open" à "false".

La création de notre requête se fait en trois étapes :

  • Instanciation de l'objet XMLHttpRequest
  • Initialisation de la requête avec la méthode open, qui prend trois paramètres :
    • Méthode HTTP (GET, POST, PUT ou DELETE pour nous)
    • Url de l'API
    • Asynchrone (booléen)
  • Envoi de la requête avec la méthode send

Le code est ainsi le suivant

// Instanciation de l'objet
let req = new XMLHttpRequest();

// Spécifie la méthode, l'url et le type d'exécution à utiliser (ici false = synchrone)
req.open("GET", "http://url_de_votre_api", false);

// Envoie la requête
req.send();

Une fois la requête envoyée, nous pouvons traiter la réponse, par exemple comme ci-dessous en vérifiant le "status" et en affichant un message

// On vérifie qu'on reçoit une réponse 200 - Ok
if(req.status == 200){
    console.log("Ca fonctionne");
}else{
    console.log("Erreur");
}

Envoyer une requête asynchrone

Le mode conseillé pour l'envoi de requêtes est le mode asynchrone. Celui-ci permet de dissocier l'envoi et le traitement de la requête du reste du code, ne pénalisant pas l'expérience des utilisateurs.

Pour envoyer la requête en mode asynchrone, il faut prendre en compte le fait que le code de traitement ne doit être exécuté qu'à la condition que les données ont bien été reçues.

Pour ce faire, nous avons accès aux évènements déclenchés par l'objet XMLHttpRequest, et en particulier "onreadystatechange", qui se déclenche à chaque changement de la propriété "readyState".

Nous allons donc structurer notre code de façon à ce que le traitement ne se déclenche pas avant que "readyState" soit à 4.

// Instanciation de l'objet
let req = new XMLHttpRequest();

// Ecouteur d'évènement sur changement de l'état prêt
req.onreadystatechange = function() {
    // Si le statut est 4 ET une réponse OK a été reçue
    if (req.readyState == 4 && (req.status == 200 || req.status == 0)) {
        console.log(req.response);
    } else if (req.readyState < 4) {
        console.log(req.readyState);
    }
};

// Spécifie la méthode, l'url et le type d'exécution à utiliser (ici en mode asynchrone)
req.open("GET", "http://url_de_votre_api", true);

// Envoie la requête
req.send();

Traiter les données

Ue fois les données reçues, nous pouvons les traiter. Dans notre exemple, nous recevons du json, nous allons donc pouvoir l'utiliser après l'avoir converti en objet Javascript

// Conversion du json en objet Javascript
let donnees = JSON.parse(req.response);

// ES8: Traitement de l'objet au moyen de la méthode entries()
// Dans le .forEach, nous avons accès aux différentes données
Object.entries(donnees.produits).forEach(element => {
    console.log(element);
});

Utiliser la méthode POST

Dans les exemples ci-dessus nous avons utilisé la méthode GET, pour lire des données. Nous aurons parfois besoin de créer des enregistrements par l'intermédiaire de l'API et donc de lui envoyer des données.

Cet envoi se fera au moyen du json et de la méthode POST.

Nous allons donc définir un produit sous forme d'objet Javascript puis le transformer en json lors de l'envoi.

La déclaration de l'objet se fait comme ceci

let produit = {
    nom: "Produit1",
    description: "Ceci est le produit 1",
    prix: 89,
    categories_id: 3
}

Nous ouvrons ensuite la requête POST

req.open("POST", "http://url_de_votre_api", true);

Et nous envoyons les données en les convertissant en json

req.send(JSON.stringify(produit));

Le code complet est donc le suivant

// Instanciation de l'objet
let req = new XMLHttpRequest();

// Ecouteur d'évènement sur changement de l'état prêt
req.onreadystatechange = function() {
    if (req.readyState == 4 && (req.status == 201 || req.status == 0)) {
        console.log(req.response);
    } else if (req.readyState < 4) {
        console.log(req.readyState);
    }
};

// Stockage des données à envoyer dans un objet
let produit = {
    nom: "Produit1",
    description: "Ceci est le produit 1",
    prix: 89,
    categories_id: 3
}

// Spécifie la méthode, l'url et le type d'exécution à utiliser
req.open("POST", "http://url_de_votre_api", true);

// Envoie la requête avec les données en json
req.send(JSON.stringify(produit));

Utiliser la méthode PUT

La méthode PUT permet de modifier des données par l'intermédiaire de l'API. Elle fonctionne de la même façon que le POST, elle nécessite toutefois l'envoi de toutes les données de l'enregistrement à modifier, même si elles ne changent pas. Il faut également penser à y inclure l'id de cet enregistrement.

En utilisation complète, la méthode PUT doit créer l'enregistrement si il n'existe pas.

Le code sera très similaire à celui de la méthode POST et sera le suivant

// Instanciation de l'objet
let req = new XMLHttpRequest();

// Ecouteur d'évènement sur changement de l'état prêt
req.onreadystatechange = function() {
    if (req.readyState == 4 && (req.status == 200 || req.status == 0)) {
        console.log(req.response);
    } else if (req.readyState < 4) {
        console.log(req.readyState);
    }
};

// Stockage des données à envoyer dans un objet
let produit = {
    id: 67,
    nom: "Produit1",
    description: "Ceci est le produit 1 modifié",
    prix: 79,
    categories_id: 3
}

// Spécifie la méthode, l'url et le type d'exécution à utiliser
req.open("PUT", "http://url_de_votre_api", true);

// Envoie la requête avec les données en json
req.send(JSON.stringify(produit));

Utiliser la méthode DELETE

La méthode DELETE, quant à elle, permet de supprimer des données par l'intermédiaire de l'API. Elle nécessite l'envoi de données, mais cette fois, uniquement l'id de l'enregistrement à supprimer.

Le code sera le suivant

// Instanciation de l'objet
let req = new XMLHttpRequest();

// Ecouteur d'évènement sur changement de l'état prêt
req.onreadystatechange = function() {
    if (req.readyState == 4 && (req.status == 200 || req.status == 0)) {
        console.log(req.response);
    } else if (req.readyState < 4) {
        console.log(req.readyState);
    }
};

// Stockage des données à envoyer dans un objet
let produit = {
    id: 69
}

// Spécifie la méthode, l'url et le type d'exécution à utiliser
req.open("DELETE", "http://url_de_votre_api", true);

// Envoie la requête avec les données en json
req.send(JSON.stringify(produit));

 Equivalence ajax en jQuery

Nous terminons cet article par une petite équivalence avec jQuery.

Les créateurs de cette bibliothèque ont créé des fonctions qui permettent de simplifier la gestion d'ajax.

La méthode principale s'appelle "$.ajax" et se décompose en plusieurs parties comme indiqué ci-dessous

// Equivalent en jQuery pour la méthode GET
$.ajax({
    url: "http://url_de_votre_api"
}).done(function(reponse){
    // Code à exécuter si la requête a fonctionné
}).fail(function(error){
    // Code à exécuter en cas d'erreur
}).always(function(){
    // Code à exécuter dans tous les cas
});

Si vous souhaitez utiliser la méthode POST, par exemple, avec envoi d'un produit, le code sera le suivant

// Stockage des données à envoyer dans un objet
let produit = {
    nom: "Produit1",
    description: "Ceci est le produit 1",
    prix: 89,
    categories_id: 3
}

// Equivalent en jQuery pour la méthode POST
$.ajax({
    url: "http://url_de_votre_api",
    type: "post",
    data: JSON.stringify(produit)
}).done(function(reponse){
    // Code à exécuter si la requête a fonctionné
}).fail(function(error){
    // Code à exécuter en cas d'erreur
}).always(function(){
    // Code à exécuter dans tous les cas
});

Voilà qui termine cet article, merci pour le temps que vous y avez consacré.

Visualisez les fichiers de cette série sur GitHub

Commentaires

Ecrire un commentaire

Pas encore de commentaire

Ecrire un commentaire