Dans ce laboratoire, vous apprendrez les compétences essentielles pour interagir avec les API web en utilisant JavaScript moderne. Vous explorerez l'API fetch, un outil puissant et flexible intégré aux navigateurs web, pour effectuer des requêtes réseau asynchrones. L'objectif principal est de comprendre comment demander des données à un serveur, gérer la réponse et gérer les erreurs potentielles, formant ainsi une compétence fondamentale pour la création d'applications web dynamiques.
Vous commencerez par effectuer une requête GET de base pour récupérer des données, puis vous apprendrez à gérer la réponse, à l'analyser en tant que JSON et à afficher les données récupérées dans un élément HTML. Le laboratoire couvre également des aspects cruciaux tels que la mise en œuvre d'une gestion d'erreurs robuste, l'exécution de requêtes POST pour envoyer des données à un serveur et l'authentification de vos requêtes à l'aide d'une clé API.
Effectuer une requête GET de base avec l'API fetch
Dans cette étape, vous apprendrez à effectuer un appel API fondamental en JavaScript : une requête GET. Nous utiliserons l'API fetch, un outil moderne, puissant et flexible intégré à tous les navigateurs web modernes et disponible dans les environnements Node.js 18+. Il nous permet de demander des ressources à un serveur de manière asynchrone.
La fonction fetch est basée sur les promesses (promises), ce qui signifie qu'elle retourne une Promise qui se résout avec la Response de cette requête, qu'elle ait réussi ou non. Cela nous permet de gérer le résultat de l'opération asynchrone une fois qu'elle est terminée.
Tout d'abord, créons un fichier pour écrire notre code. Dans l'explorateur de fichiers sur le côté gauche de votre écran, créez un nouveau fichier nommé index.js dans le répertoire ~/project.
Nous utiliserons l'API JSONPlaceholder pour cet exemple. C'est une API REST en ligne, gratuite et fictive, parfaite pour les tests et le prototypage. Nous demanderons un seul élément "todo".
Maintenant, ajoutez le code suivant à votre fichier index.js. Ce code définit l'URL du point d'accès de l'API et utilise fetch pour effectuer une requête GET.
// Define the API URL for a single todo item
const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";
// Make a GET request using the fetch API
fetch(apiUrl)
.then((response) => {
// The fetch function returns a promise.
// The first .then() block receives the Response object.
// We need to call the .json() method on the response to parse the body text as JSON.
return response.json();
})
.then((data) => {
// The second .then() block receives the parsed JSON data.
console.log("Data fetched successfully:");
console.log(data);
})
.catch((error) => {
// The .catch() block will execute if any error occurs during the fetch operation.
console.error("Error fetching data:", error);
});
Analysons le code :
apiUrl : Nous stockons l'URL du point d'accès de l'API que nous voulons contacter dans une constante.
fetch(apiUrl) : Ceci initie la requête GET à l'URL spécifiée et retourne une Promise.
.then(response => response.json()) : Lorsque la Promise se résout, cette fonction est appelée. L'objet response n'est pas les données JSON réelles, mais une représentation de la réponse HTTP complète. Nous appelons la méthode response.json() pour extraire le contenu du corps JSON, qui retourne elle-même une autre Promise.
.then(data => { ... }) : Ce second .then() gère la Promise retournée par response.json(). Le paramètre data contient maintenant l'objet JSON réel de l'API. Nous affichons ces données dans la console.
.catch(error => { ... }) : Si la Promise est rejetée à un moment donné (par exemple, en raison d'une erreur réseau), ce bloc attrapera l'erreur et l'affichera dans la console.
Pour exécuter votre script et voir le résultat, ouvrez un nouveau terminal dans le WebIDE et exécutez la commande suivante :
node ~/project/index.js
Vous devriez voir les données récupérées s'afficher dans votre console, représentant un seul élément "todo" de l'API.
Sortie attendue :
Data fetched successfully:
{ userId: 1, id: 1, title: 'delectus aut autem', completed: false }
Gérer la réponse et analyser les données JSON
Dans cette étape, nous allons approfondir la gestion de la réponse d'un appel API. Lorsque vous utilisez fetch, le serveur renvoie un objet Response. Nous allons explorer ce que cet objet contient et comment analyser correctement les données JSON de son corps pour les utiliser dans votre application.
L'objet Response que vous recevez dans le premier bloc .then() n'est pas la donnée elle-même. C'est une représentation de la réponse HTTP complète, incluant les codes de statut (comme 200 pour OK), les en-têtes (headers) et le corps de la réponse (response body). Le corps est un flux de données, et pour l'utiliser, vous devez le lire.
L'API fetch fournit plusieurs méthodes pour cela, comme .text() pour le texte brut et .json() pour l'analyse des données JSON. La méthode .json() lit le flux de réponse jusqu'à sa complétion et retourne une nouvelle promesse qui se résout avec le résultat de l'analyse du texte du corps en tant qu'objet JavaScript. C'est pourquoi nous chaînons un second .then() pour travailler avec les données réelles.
Modifions notre fichier ~/project/index.js pour démontrer cela. Au lieu de simplement afficher l'objet de données complet, nous allons accéder et afficher des propriétés spécifiques de celui-ci, montrant que nous avons un objet JavaScript régulier avec lequel travailler.
Mettez à jour le contenu de votre fichier ~/project/index.js avec le code suivant :
// Define the API URL for a single todo item
const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";
fetch(apiUrl)
.then((response) => {
// The response.json() method parses the JSON body of the response
// and returns a promise that resolves with the resulting JavaScript object.
return response.json();
})
.then((data) => {
// Now 'data' is a JavaScript object. We can access its properties.
console.log("Successfully parsed JSON data:");
console.log(`Todo Title: ${data.title}`);
console.log(`Is Completed: ${data.completed}`);
})
.catch((error) => {
// The .catch() block will execute if any error occurs during the fetch operation.
console.error("Error fetching or parsing data:", error);
});
Dans ce code mis à jour, le second bloc .then() reçoit maintenant les data sous forme d'objet JavaScript. Nous utilisons des littéraux de gabarit (template literals, la syntaxe avec les guillemets inversés `) pour créer des chaînes de caractères qui incluent les valeurs de data.title et data.completed, démontrant que le JSON a été analysé avec succès.
Exécutez maintenant à nouveau le script dans votre terminal pour voir le nouveau résultat :
node ~/project/index.js
Vous verrez une sortie plus structurée, confirmant que vous avez accédé avec succès aux propriétés de l'objet JSON analysé.
Sortie attendue :
Successfully parsed JSON data:
Todo Title: delectus aut autem
Is Completed: false
Afficher les données récupérées dans un élément HTML
Dans cette étape, vous apprendrez à récupérer les données d'un appel API et à les afficher sur une page web. Bien que l'affichage des données dans la console soit utile pour le développement, l'objectif final est souvent de présenter ces informations à l'utilisateur. Cela nécessite un fichier HTML pour structurer le contenu et du JavaScript pour manipuler le Document Object Model (DOM).
Tout d'abord, nous avons besoin d'un fichier HTML. Dans l'explorateur de fichiers à gauche, créez un nouveau fichier nommé index.html dans le répertoire ~/project.
Ajoutez la structure HTML de base suivante à votre fichier index.html. Ce fichier comprend un titre et un élément div avec l'ID data-output, qui servira de conteneur pour nos données récupérées. La balise <script> à la fin du corps garantit que notre JavaScript s'exécute après le chargement des éléments HTML.
Ensuite, vous devez modifier votre fichier ~/project/index.js pour interagir avec ce HTML. Au lieu d'afficher dans la console, le script trouvera l'élément div par son ID et mettra à jour son contenu avec les données de l'API.
Remplacez le contenu de ~/project/index.js par le code suivant :
const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";
// Select the HTML element where we will display the data
const outputElement = document.getElementById("data-output");
fetch(apiUrl)
.then((response) => response.json())
.then((data) => {
// Once we have the data, we update the HTML content.
// We use innerHTML to replace the "Loading..." message with structured data.
outputElement.innerHTML = `
<p><strong>Title:</strong> ${data.title}</p>
<p><strong>Completed:</strong> ${data.completed}</p>
`;
})
.catch((error) => {
// If an error occurs, display an error message to the user.
outputElement.textContent = "Failed to load data.";
console.error("Error fetching data:", error);
});
Maintenant, pour voir le résultat, vous devez servir ces fichiers via un serveur web. L'environnement LabEx inclut Python, qui dispose d'un serveur web intégré simple.
Ouvrez un nouveau terminal dans le WebIDE.
Démarrez le serveur web en exécutant la commande suivante. Cela servira les fichiers du répertoire courant (~/project) sur le port 8080.
python3 -m http.server 8080
La plateforme LabEx détectera ce service en cours d'exécution et fournira un onglet "Web 8080" pour prévisualiser votre page index.html.
Vous devriez maintenant voir votre page web afficher le titre et le statut de complétion de l'élément "todo" récupéré, remplaçant le message initial "Loading data...".
Implémenter la gestion des erreurs pour les appels API
Dans cette étape, nous allons nous concentrer sur la robustesse de notre appel API en implémentant une gestion appropriée des erreurs. Les requêtes API peuvent échouer pour diverses raisons, telles qu'une URL incorrecte, des problèmes de réseau ou des problèmes côté serveur. Il est crucial de gérer ces échecs potentiels avec élégance pour offrir une meilleure expérience utilisateur.
Un détail important concernant l'API fetch est que sa promesse ne rejette pas les statuts d'erreur HTTP comme 404 (Not Found) ou 500 (Internal Server Error). Elle ne rejette que s'il y a une défaillance réseau qui empêche la requête de s'achever. Pour gérer les erreurs HTTP, nous devons vérifier la propriété response.ok, qui est true pour les réponses réussies (codes de statut 200-299).
Mettons à jour notre ~/project/index.js pour vérifier le statut de la réponse et gérer les erreurs potentielles.
Remplacez le contenu de votre fichier ~/project/index.js par le code suivant. Nous ajoutons une vérification dans le premier bloc .then().
const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";
const outputElement = document.getElementById("data-output");
fetch(apiUrl)
.then((response) => {
// Check if the response was successful.
// The 'ok' property is a boolean that is true if the status code is in the 200-299 range.
if (!response.ok) {
// If not, we throw an error which will be caught by the .catch() block.
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then((data) => {
outputElement.innerHTML = `
<p><strong>Title:</strong> ${data.title}</p>
<p><strong>Completed:</strong> ${data.completed}</p>
`;
})
.catch((error) => {
// Display a user-friendly error message in the HTML element.
outputElement.textContent = "Failed to load data. Please try again later.";
// Log the technical error to the console for debugging purposes.
console.error("Error fetching data:", error);
});
Pour voir notre gestion des erreurs en action, utilisons intentionnellement une URL API invalide. Modifiez apiUrl dans ~/project/index.js pour qu'elle pointe vers une ressource qui n'existe pas. Cela provoquera une erreur 404 Not Found de la part de l'API.
Changez cette ligne dans votre fichier index.js : const apiUrl = 'https://jsonplaceholder.typicode.com/todos/1';
Par celle-ci : const apiUrl = 'https://jsonplaceholder.typicode.com/invalid-path/1';
Voyons maintenant le résultat. Si votre serveur web Python de l'étape précédente est toujours en cours d'exécution, actualisez simplement l'onglet de prévisualisation dans votre navigateur. Si vous l'avez arrêté, redémarrez-le depuis le terminal :
python3 -m http.server 8080
Ouvrez ensuite la prévisualisation. Au lieu des données, vous devriez voir le message d'erreur affiché sur la page car notre vérification if (!response.ok) a intercepté l'erreur 404.
Sortie attendue sur la page Web :
Failed to load data. Please try again later.
Important : Avant de passer à l'étape suivante, n'oubliez pas de rétablir l'apiUrl à la valeur correcte : https://jsonplaceholder.typicode.com/todos/1.
Effectuer une requête POST pour envoyer des données
Dans cette étape, vous apprendrez à envoyer des données à un serveur à l'aide d'une requête POST. Jusqu'à présent, nous n'avons fait que récupérer (ou "GET") des données. Une requête POST est utilisée pour soumettre des données à une ressource spécifiée, provoquant souvent un changement d'état ou la création d'une nouvelle entrée sur le serveur.
Pour ce faire, nous devons fournir plus d'informations à la fonction fetch, notamment la méthode de requête, les en-têtes (headers) pour décrire les données que nous envoyons, et les données elles-mêmes dans le corps de la requête (request body).
Tout d'abord, mettons à jour notre fichier ~/project/index.html pour inclure un formulaire. Cela nous permettra de saisir des données que nous pourrons ensuite envoyer à l'API. Remplacez l'intégralité du contenu de index.html par ce qui suit :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>POST Request Example</title>
</head>
<body>
<h1>Create a New Todo Item</h1>
<form id="add-todo-form">
<input
type="text"
id="todo-title"
placeholder="Enter a new todo title"
required
/>
<button type="submit">Add Todo</button>
</form>
<hr />
<h2>Server Response:</h2>
<div id="response-output"></div>
<script src="index.js"></script>
</body>
</html>
Ce HTML crée un formulaire simple avec un champ de saisie de texte et un bouton de soumission, ainsi qu'un div pour afficher la réponse du serveur.
Ensuite, nous allons remplacer entièrement le code dans ~/project/index.js pour gérer la soumission du formulaire et effectuer une requête POST.
Remplacez le contenu de ~/project/index.js par le code suivant :
// The API endpoint for creating new todos
const apiUrl = "https://jsonplaceholder.typicode.com/todos";
// Get the form and the response output element from the DOM
const todoForm = document.getElementById("add-todo-form");
const responseOutput = document.getElementById("response-output");
// Add an event listener for the form's submit event
todoForm.addEventListener("submit", function (event) {
// Prevent the default form submission behavior
event.preventDefault();
// Get the title from the input field
const todoTitle = document.getElementById("todo-title").value;
// The data we want to send in the POST request
const newTodo = {
title: todoTitle,
completed: false,
userId: 1
};
// The options for the fetch request
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(newTodo)
};
// Make the POST request
fetch(apiUrl, requestOptions)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// The API returns the created object, including a new 'id'
return response.json();
})
.then((data) => {
// Display the server's response in our output div
responseOutput.innerHTML = `<p>Successfully created todo!</p><pre>${JSON.stringify(data, null, 2)}</pre>`;
})
.catch((error) => {
responseOutput.textContent = "Failed to create todo.";
console.error("Error:", error);
});
});
Décomposons le nouvel objet requestOptions :
method: 'POST': Ceci indique à fetch d'effectuer une requête POST.
headers: { 'Content-Type': 'application/json' }: Cet en-tête informe le serveur que les données dans le corps sont au format JSON.
body: JSON.stringify(newTodo): Ce sont les données réelles que nous envoyons. Elles doivent être converties en une chaîne JSON avant d'être envoyées.
Maintenant, démarrez à nouveau votre serveur web s'il n'est pas en cours d'exécution :
python3 -m http.server 8080
Ouvrez la prévisualisation, tapez un titre pour un nouvel élément de tâche dans le champ de saisie, et cliquez sur le bouton "Add Todo". Vous devriez voir un message de succès et les données renvoyées par le serveur, qui incluent le nouvel id pour l'élément que vous avez "créé".
Authentifier les requêtes avec une clé API
Dans cette étape, vous apprendrez à authentifier vos requêtes API à l'aide d'une clé API (API key). De nombreuses API nécessitent une authentification pour identifier l'utilisateur, contrôler l'accès aux données et suivre l'utilisation. Une clé API est une chaîne de caractères unique que vous incluez dans votre requête pour prouver que vous avez l'autorisation d'utiliser l'API.
Il existe plusieurs façons d'envoyer une clé API, mais une méthode courante et sécurisée consiste à l'inclure dans les en-têtes de requête (request headers), généralement en utilisant l'en-tête Authorization.
Pour cet exemple, nous allons simuler la récupération de données utilisateur protégées qui nécessitent une clé API. Nous allons modifier notre code pour inclure un en-tête Authorization avec un jeton "Bearer", qui est une manière standard d'envoyer des informations d'identification d'authentification.
Tout d'abord, simplifions notre fichier ~/project/index.html pour qu'il affiche uniquement les données utilisateur récupérées. Remplacez son contenu par ce qui suit :
Ensuite, remplacez le contenu de ~/project/index.js par le code ci-dessous. Ce script effectuera une requête GET pour récupérer les données d'un utilisateur et inclura une fausse clé API dans les en-têtes.
// Define the API URL for a user's profile
const apiUrl = "https://jsonplaceholder.typicode.com/users/1";
// In a real application, you would get this key from your API provider.
const apiKey = "YOUR_SECRET_API_KEY_HERE";
// Select the HTML element for output
const userProfileElement = document.getElementById("user-profile");
// Create the request options object, including the headers for authentication
const requestOptions = {
method: "GET",
headers: {
Authorization: `Bearer ${apiKey}`
}
};
// Make the authenticated GET request
fetch(apiUrl, requestOptions)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then((data) => {
// Display the fetched user data
userProfileElement.innerHTML = `
<p><strong>Name:</strong> ${data.name}</p>
<p><strong>Email:</strong> ${data.email}</p>
<p><strong>Website:</strong> ${data.website}</p>
`;
})
.catch((error) => {
userProfileElement.textContent = "Failed to load user profile.";
console.error("Error:", error);
});
Dans ce code :
Nous définissons une clé API (apiKey) fictive.
Nous créons un objet requestOptions.
À l'intérieur de headers, nous ajoutons une clé Authorization. La valeur Bearer ${apiKey} est un format courant, où "Bearer" est le type de jeton, suivi de la clé elle-même.
Remarque : L'API JSONPlaceholder que nous utilisons est publique et ne nécessite pas réellement de clé API. Elle ignorera simplement cet en-tête. Cependant, ce code démontre la méthode standard que vous utiliseriez pour les nombreuses API du monde réel qui nécessitent une authentification.
Pour voir le résultat, démarrez votre serveur web s'il n'est pas déjà en cours d'exécution :
python3 -m http.server 8080
Ensuite, ouvrez la prévisualisation. La page se chargera avec succès et affichera le profil de l'utilisateur, démontrant que vous avez correctement structuré une requête API authentifiée.
Résumé
Dans ce laboratoire, vous avez appris à appeler une API en JavaScript en utilisant la nouvelle API fetch. Vous avez commencé par effectuer une requête GET de base pour récupérer des données à partir d'un point de terminaison d'API public. Vous vous êtes exercé à gérer la nature asynchrone de fetch en utilisant des promesses, en chaînant des blocs .then() pour traiter la réponse et analyser le corps du texte en JSON. Les compétences clés comprenaient l'affichage dynamique des données récupérées dans un élément HTML et la mise en œuvre d'une gestion d'erreurs robuste avec un bloc .catch() pour gérer les échecs potentiels du réseau.
En vous appuyant sur ces fondamentaux, vous avez exploré comment envoyer des données à un serveur en construisant et en exécutant une requête POST, y compris les en-têtes nécessaires et une charge utile JSON. Enfin, vous avez appris une méthode courante pour sécuriser les communications API en authentifiant vos requêtes, ce qui impliquait d'inclure une clé API pour obtenir un accès autorisé aux ressources protégées.