- Apprendre
- Informatique et numérique
- Programmation
- JavaScript : DOM, événements et code asynchrone
- Fetch et API du navigateur
Fetch et API du navigateur : récupérer des données
fetch, à afficher les résultats sur une page web et à conserver de petites quantités de données dans le navigateur. Tu lis des requêtes et des réponses HTTP ainsi que du JSON, tu gères les états de chargement et d’erreur et tu mets en forme les dates et les prix d’une API pour chaque lecteur. Tu découvres pourquoi les erreurs CORS se produisent et pourquoi les clés d’API secrètes n’ont pas leur place dans le code côté client, puis tu utilises localStorage, sessionStorage et des fonctionnalités du navigateur comme la géolocalisation et le presse-papiers.DébutantUnité 8 sur 9 de la formation Formation : JavaScript : DOM, événements et code asynchrone
Ce que tu vas apprendre
- Explique comment fonctionnent une requête et une réponse HTTP, charge des données JSON avec
fetchet envoie des données à une API avec la méthode, les en-têtes et le corps appropriés.- Lis les requêtes et les réponses HTTPDécris les parties d’une requête et d’une réponse HTTP, associe chaque méthode HTTP à son action et lis les codes d’état et les en-têtes dans les outils de développement du navigateur.
- Charge des données JSON avec fetchAppelle
fetch, vérifie l’état de la réponse, lis et analyse son corps JSON et construis des URL de requête avec des paramètres de requête correctement encodés. - Envoie des données avec POST, PUT, PATCH et DELETEPasse un objet d’options à
fetchpour envoyer du JSON ou des données de formulaire, et traite la réponse du serveur après avoir créé, mis à jour ou supprimé un enregistrement.
- Lis les requêtes et les réponses HTTP
- Transforme les résultats d’une API en contenu de page, mets en forme les dates et les montants pour le lecteur et garde la page claire pendant le chargement, en cas d’échec ou lorsque les données arrivent dans le désordre.
- Affiche les résultats d’une API dans la pageConstruis des éléments de page à partir des tableaux et des objets d’une réponse JSON, insère le texte de l’API en toute sécurité et gère les champs manquants, les résultats vides et les résultats paginés.
- Mets en forme les dates, les nombres et les montants monétaires issus des données d’une APIConvertis les chaînes de date, les horodatages et les montants envoyés par les API en texte lisible adapté à la langue, à la région et au fuseau horaire du lecteur avec les outils de mise en forme
Intl. - Affiche les états de chargement, d’erreur et d’absence de donnéesSuis les étapes d’une requête, affiche un message clair à l’utilisateur pour chaque étape et réagis aux échecs par de nouvelles tentatives.
- Annule des requêtes, limite leur durée et combine-lesAnnule les requêtes devenues inutiles, définis des limites de durée, empêche les réponses obsolètes de remplacer les plus récentes et exécute plusieurs requêtes en parallèle ou en séquence.
- Affiche les résultats d’une API dans la page
- Explique la politique de même origine et les erreurs CORS, et protège les clés d’API et les données des utilisateurs lorsqu’une page communique avec d’autres serveurs.
- Comprends la politique de même origine et le partage de ressources entre originesIdentifie l’origine d’une URL, explique pourquoi le navigateur bloque certaines réponses provenant d’autres origines et reconnais comment les en-têtes CORS et les requêtes préliminaires permettent à un serveur de les autoriser.
- Protège les clés d’API et les données des utilisateursExplique le rôle des clés d’API et des jetons, pourquoi un secret dans le code côté client est public et comment envoyer les identifiants et traiter les données des utilisateurs de manière responsable.
- Comprends la politique de même origine et le partage de ressources entre origines
- Enregistre, lis et mets à jour de petites quantités de données avec localStorage et sessionStorage, et détermine ce qu’il est judicieux et sûr de conserver dans le navigateur.
- Enregistre et lis des données avec localStorage et sessionStorageUtilise les méthodes de Web Storage, explique la durée de conservation de chaque type de stockage et qui peut le lire, et convertis des nombres, des booléens et des objets en chaînes de caractères stockées et inversement.
- Utilise le stockage du navigateur dans une applicationRestaure l’état enregistré au chargement d’une page, mets en cache les réponses d’une API avec une durée d’expiration, synchronise les onglets et décide de ce qui ne doit pas être stocké.
- Enregistre et lis des données avec localStorage et sessionStorage
- Détecte et utilise les API du navigateur qui nécessitent une page sécurisée ou l’autorisation de l’utilisateur, comme la géolocalisation et le presse-papiers, et propose une solution de repli lorsqu’une fonctionnalité est indisponible.
- Obtiens la position de l’utilisateur avec l’API de géolocalisationVérifie qu’une API du navigateur est disponible, explique les contextes sécurisés et les demandes d’autorisation, et utilise l’API de géolocalisation avec ses options, ses erreurs et une solution de repli.
- Copie du texte et utilise d’autres API du navigateurCopie du texte avec l’API du presse-papiers, réagis aux changements de connectivité, lis les paramètres de l’adresse de la page et suis une méthode pour découvrir toute nouvelle API du navigateur.
- Obtiens la position de l’utilisateur avec l’API de géolocalisation
Fetch et API du navigateur : cours
1Effectue des requêtes et lis les réponses
Une page peut demander des données à un serveur sans charger une nouvelle page. La requête indique quelle ressource tu veux et ce que tu veux en faire ; la réponse indique ce qui s’est passé. Tu suivras cet échange dans l’onglet Réseau, convertiras une réponse JSON en données JavaScript et enverras des modifications au serveur. Les points à vérifier sont la méthode, le code d’état et la structure du corps : l’arrivée d’une réponse ne signifie pas à elle seule que l’opération a réussi.
1.1 Les éléments d’un échange HTTP
Une API web permet à un programme de lire ou de modifier des données au moyen d’URL nommées, appelées points de terminaison. Le JavaScript de la page est le client. Il envoie une requête HTTP ; le serveur répond avec une réponse HTTP. De nombreuses API envoient du texte JSON, qui peut représenter des objets, des tableaux, des chaînes de caractères, des nombres, des booléens et null.
Lire une requête
Prenons GET https://api.example.com/books?author=Le%20Guin&limit=5. La méthode est GET, le chemin /books sélectionne la ressource et la chaîne de requête contient deux paramètres. La valeur de author est « Le Guin » ; %20 encode l’espace. Une esperluette sépare les paramètres. La documentation de l’API explique les noms de paramètres acceptés et le sens de chaque valeur.
Une requête peut aussi transporter des en-têtes, qui sont des paires nom-valeur, et un corps, qui contient les données soumises. Accept: application/json demande une réponse JSON. Content-Type: application/json décrit le corps envoyé. Authorization transporte des identifiants. Les noms d’en-tête ne tiennent pas compte de la casse : content-type et Content-Type désignent donc le même en-tête.
Choisir l’action
| Méthode | Action prévue | Utilisation habituelle |
|---|---|---|
GET | Lire | Obtenir une liste de notes |
POST | Créer ou soumettre | Ajouter une note |
PUT | Remplacer | Envoyer la note complète de remplacement |
PATCH | Modifier une partie | Marquer une note comme terminée |
DELETE | Supprimer | Supprimer une note |
GET et HEAD sont des méthodes sûres : elles sont destinées à la lecture. N’utilise donc pas GET pour un bouton de suppression. GET, PUT et DELETE sont idempotentes. Répéter la même requête laisse le serveur dans le même état attendu qu’une seule exécution. Supprimer une note déjà supprimée peut renvoyer un code d’état différent, mais la note reste absente. Répéter un POST peut créer un second enregistrement.
Interpréter la réponse
La réponse contient un code d’état, des en-têtes et généralement un corps. Le premier chiffre classe le résultat :
- 2xx : succès.
200 OKcontient généralement des données,201 Createdindique une création et204 No Contentn’a pas de corps. - 3xx : redirection. Par défaut,
fetchsuit les redirections. - 4xx : problème lié à la requête ou à l’accès.
400signifie que la requête est incorrecte ;401, que les identifiants sont absents ou invalides ;403, que le serveur comprend la requête mais la refuse ;404, que la ressource est introuvable ;429, qu’il y a trop de requêtes. - 5xx : problème de serveur, comme
500 Internal Server Errorou503 Service Unavailable.
Un appel à /books/42 peut renvoyer 200, un type de contenu JSON et {"id":42,"title":"The Dispossessed","year":1974}. Un appel à /books/9999 peut renvoyer 404 et {"error":"Book not found"}. Les deux appels ont reçu une réponse. Une erreur de connexion ne produit aucun code d’état HTTP que JavaScript puisse examiner.
Examiner avant de supposer
Ouvre les outils de développement, sélectionne Réseau et déclenche l’action. Examine la méthode, l’URL complète, le code d’état, les en-têtes, le corps et les durées. Compare-les au point de terminaison, aux paramètres obligatoires, aux identifiants, aux limites de requêtes et à l’exemple de réponse de la documentation. Si le serveur a renvoyé les bonnes données, examine le code de la page ; si l’URL de la requête est incorrecte, corrige-la avant de modifier le code de rendu.
Points clés
- Un point de terminaison est une URL qu’une API expose pour une opération.
- La méthode sélectionne l’action ; l’URL sélectionne la ressource et les paramètres.
- Les en-têtes de requête et de réponse décrivent l’échange.
- Un
404est une réponse, tandis qu’une erreur de connexion n’a pas de code d’état HTTP. - Examine l’onglet Réseau et compare l’échange à la documentation de l’API.
1.2 Charge du JSON en deux étapes asynchrones
fetch(url) envoie une requête GET et renvoie une promesse. Son résultat est un objet Response, disponible à l’arrivée des en-têtes. La lecture du corps est une opération asynchrone distincte. response.json() lit ce corps et l’analyse pour obtenir des données JavaScript.
Attendre, vérifier, lire
async function loadBook(id) {
const response = await fetch(`https://api.example.com/books/${id}`);
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`);
}
return await response.json();
}
Pour loadBook(42), le premier await obtient la réponse. La condition rejette un résultat HTTP indiquant un échec. Le second await obtient le livre analysé, par exemple { id: 42, title: "The Dispossessed", year: 1974 }. La fonction elle-même renvoie une promesse : son appelant attend donc aussi le résultat.
response.ok est vrai pour les codes d’état de 200 à 299 inclus. Une erreur HTTP comme 404 ou 500 ne provoque pas le rejet de la promesse de fetch : un serveur a répondu. Une panne réseau, un échange bloqué par CORS, une URL de requête invalide ou une annulation peuvent provoquer son rejet. Lever une exception pour !response.ok permet à un bloc try/catch englobant de gérer aussi les échecs HTTP.
Comprendre le corps
Sans await, const data = response.json() stocke une promesse, pas le livre. L’accès à data.title donne alors undefined. Omettre await devant fetch laisse de même une promesse là où le code attend un objet Response.
Choisis la méthode de lecture adaptée au corps de la réponse : json() pour le JSON, text() pour le texte ou blob() pour les données binaires. Un corps ne peut être consommé qu’une fois. Stocke le résultat analysé et réutilise-le. Pour examiner aussi le texte JSON brut, lis text() une fois, puis appelle JSON.parse(text) sur la chaîne stockée.
Du JSON invalide entraîne un rejet avec une SyntaxError. Une page d’erreur HTML provoque souvent un message « Unexpected token '<' ». Un corps vide, notamment dans une réponse 204, ne peut pas non plus être analysé comme du JSON. Vérifie d’abord le code d’état et examine response.headers.get("Content-Type") en cas de doute sur le format. Un code d’état de succès ne garantit pas à lui seul que le corps contient du JSON.
Construire une requête en toute sécurité
const url = new URL("https://api.example.com/search");
url.searchParams.set("q", "rock & roll");
url.searchParams.set("limit", 10);
L’adresse obtenue est https://api.example.com/search?q=rock+%26+roll&limit=10. L’esperluette incluse dans la valeur est encodée comme partie de celle-ci. Ajouter directement la saisie à "?q=" peut donner à &, # ou + leur signification dans une URL et modifier la recherche. Une URL relative suit les règles habituelles de résolution des adresses : depuis https://notes.example.org/app/index.html, fetch("data/books.json") charge /app/data/books.json sur cette origine.
Suivre la structure renvoyée
Pour {"results":[{"title":"Dune"}],"total":1}, le premier titre est data.results[0].title. L’objet englobant n’est pas le tableau de résultats. Utilise l’aperçu de la réponse pour trouver le tableau avant de le parcourir.
Une fonction utilitaire partagée getJSON(url, options) peut effectuer la même vérification du code d’état et la même lecture du corps pour de nombreux appels. Dans une chaîne .then(), renvoie response.json() depuis la fonction de rappel de la réponse afin que la suivante reçoive les données analysées. Ajoute .catch() à la fin pour gérer les étapes rejetées.
Points clés
fetchetresponse.json()renvoient des promesses distinctes.- Vérifie
response.ok; une erreur HTTP ne provoque pas le rejet defetch. - Lis le corps d’une réponse une seule fois et réutilise la valeur stockée.
- Utilise
URL.searchParamspour encoder les valeurs de requête. - Lis le JSON imbriqué selon sa structure réelle d’objets et de tableaux.
- Une réponse réussie peut tout de même contenir un corps JSON vide ou invalide.
1.3 Envoie une modification et utilise le résultat du serveur
Le second argument de fetch configure une requête. Ses options comprennent method, headers, body, signal et credentials. Sans ces options, la requête est un GET sans corps. Pour soumettre du JSON, tu dois préparer son texte et son type de contenu.
Envoyer du JSON
const response = await fetch("https://api.example.com/notes", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title: "Shopping", text: "Rice, lentils" }),
});
JSON.stringify produit {"title":"Shopping","text":"Rice, lentils"}. L’en-tête indique au serveur comment lire ce texte. Passer directement l’objet comme corps envoie "[object Object]". Envoyer la chaîne JSON sans l’en-tête lui attribue le type text/plain;charset=UTF-8, que de nombreux points de terminaison JSON rejettent avec 400 ou 415 Unsupported Media Type.
Une création réussie renvoie souvent 201 avec l’enregistrement stocké, par exemple {"id":17,"title":"Shopping","text":"Rice, lentils"}. Utilise l’objet renvoyé pour mettre la page à jour : le nouvel id attribué par le serveur est nécessaire pour les modifications et la suppression ultérieures.
Remplacer ou mettre à jour
| Requête | Corps | Signification |
|---|---|---|
PATCH /notes/17 | {"done":true} | Modifier le champ fourni |
PUT /notes/17 | La note complète de remplacement | Remplacer la ressource |
DELETE /notes/17 | Souvent aucun | Supprimer la ressource |
Un corps PUT qui omet un champ peut entraîner sa suppression ou sa réinitialisation, selon l’API. Utilise la méthode documentée pour la modification souhaitée. PUT et PATCH peuvent renvoyer un enregistrement mis à jour avec 200, ou renvoyer 204 sans corps.
Gère le succès sans supposer qu’il est toujours suivi de JSON :
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`);
}
const saved = response.status === 204
? null
: await response.json();
Ce schéma convient aux points de terminaison documentés comme renvoyant soit du JSON, soit 204. Une suppression peut réussir et produire tout de même une erreur d’analyse syntaxique si le code appelle systématiquement json() sur son corps vide.
Choisir le format du corps
new FormData(formElement) recueille les champs nommés du formulaire et les fichiers sélectionnés. Passe-le directement comme body. Laisse le navigateur définir Content-Type: multipart/form-data et son délimiteur ; un en-tête fourni manuellement peut omettre le délimiteur nécessaire pour séparer les champs. Un corps URLSearchParams utilise application/x-www-form-urlencoded.
GET et HEAD ne peuvent pas transporter de corps avec fetch. Place les termes de recherche et les filtres dans la chaîne de requête de l’URL. Une tentative de GET avec un corps est rejetée avec une TypeError avant de pouvoir servir de requête de recherche.
Terminer correctement après un succès ou un échec
Désactive le bouton de soumission avant d’attendre une requête de création, puis réactive-le dans finally. Sinon, un double clic peut envoyer deux requêtes POST et créer deux enregistrements. Ne répète pas automatiquement une opération de création dont le résultat est incertain : une réponse perdue ne permet pas de savoir si le serveur a effectué la modification.
Pour un code d’état d’erreur, le corps peut contenir un message utile comme {"error":"title is required"}. Lis-le une fois s’il s’agit de JSON ; intercepte une erreur d’analyse et conserve un message HTTP général pour les réponses vides ou HTML. Garde le texte saisi par l’utilisateur afin qu’il puisse corriger la requête.
Points clés
- Les requêtes JSON nécessitent
JSON.stringifyet un type de contenu correspondant. - Utilise
PATCHpour une modification partielle etPUTpour un remplacement complet. - Ne lance pas l’analyse JSON pour
204 No Content. - Laisse le navigateur définir l’en-tête multipart lors de l’envoi de
FormData. - Utilise la réponse du serveur, y compris l’identifiant attribué, pour mettre la page à jour.
- Empêche les soumissions en double et rétablis les commandes dans
finally.
2Transforme les réponses en une page utile
La récupération des données n’est que la première partie d’une interface. Les lecteurs ont besoin de résultats utiles, de dates et de prix lisibles et d’un message clair pendant l’attente. Tu construiras l’affichage à partir de la structure de la réponse, empêcheras les valeurs manquantes de le bloquer et rendras visibles les succès, les résultats vides et les échecs. Tu contrôleras aussi les requêtes qui se chevauchent pour qu’une réponse lente ne puisse pas remplacer des résultats plus récents, et choisiras quand des requêtes indépendantes peuvent s’exécuter ensemble.
2.1 Construis l’affichage à partir des données
Le rendu transforme un tableau ou un objet en éléments sur la page. Conserve les données récupérées dans une variable et donne-les à une fonction de rendu. Cette séparation permet de trier ou de filtrer les mêmes données sans les redemander au serveur.
Créer un élément par résultat
function renderBooks(books, list) {
list.replaceChildren();
for (const book of books) {
const item = document.createElement("li");
item.textContent = `${book.title} (${book.year})`;
list.append(item);
}
}
Pour [{"title":"Kindred","year":1979},{"title":"Beloved","year":1987}], ce code crée deux éléments de liste : « Kindred (1979) » et « Beloved (1987) ». Vider d’abord le conteneur permet à une nouvelle recherche de remplacer la précédente. Sans cette étape, les anciennes et les nouvelles listes s’accumulent.
Conserver le texte externe sous forme de texte
Utilise textContent pour les titres, descriptions et autres textes d’une API. innerHTML analyse une chaîne comme du balisage. Un titre contenant <img src="x" onerror="alert(1)"> peut alors exécuter du code. C’est une injection de script intersite, ou XSS. Le texte provenant des formulaires et du stockage nécessite le même traitement, car il peut lui aussi provenir d’une source non fiable.
Les propriétés des éléments définissent des valeurs individuelles, comme img.alt = book.title. Elles ne rendent pas automatiquement sûrs tous les types de valeurs. Un lien fourni par une API nécessite toujours une vérification du protocole :
try {
const target = new URL(book.url, location.href);
if (target.protocol === "https:" || target.protocol === "http:") {
link.href = target.href;
}
} catch {
link.removeAttribute("href");
}
Ce code s’exécute sur un lien nouvellement créé, sans href existant. Une URL invalide ou non autorisée le laisse sans destination. Une URL javascript: n’est pas une navigation web ordinaire. Pour les images, fournis si possible un texte alt pertinent construit à partir des données.
Fournir des valeurs par défaut sans perdre les valeurs réelles
Les champs facultatifs peuvent être absents ou valoir null. book.author?.name ?? "Unknown author" essaie d’abord d’obtenir le nom imbriqué, puis fournit une valeur par défaut. Le chaînage optionnel évite d’accéder à une propriété d’un auteur absent.
L’opérateur compte : 0 || "n/a" donne "n/a", tandis que 0 ?? "n/a" conserve 0. L’opérateur || remplace toutes les valeurs fausses dans un contexte booléen, notamment zéro et une chaîne vide ; ?? ne remplace que null et undefined. Pour un livre dont aucun exemplaire n’est disponible, il faut afficher zéro.
Un tableau de résultats vide correspond à une recherche réussie sans résultat. Affiche « Aucun livre ne correspond à ta recherche. » pour que les lecteurs puissent le distinguer d’une page qui n’a pas été chargée.
Remplacer une recherche, ajouter une autre page
De nombreuses API renvoient des pages à l’aide de page, limit, d’un nombre total ou d’une URL next. Avec 47 résultats et 10 par page, quatre pages complètes contiennent 40 enregistrements et la cinquième en contient 7. Une nouvelle recherche efface la liste précédente ; « Charger plus » ajoute la page suivante à la liste actuelle. Distingue bien ces deux actions d’affichage.
Pour trier une copie locale de la plus récente à la plus ancienne, utilise [...books].sort((a, b) => b.year - a.year) et affiche cette copie. La décomposition crée un nouveau tableau : l’ordre de la réponse enregistrée reste donc disponible. Examine la structure de la réponse avant de sélectionner le tableau : une API paginée le place souvent dans data.results.
Points clés
- Effectue le rendu à partir des données enregistrées pour trier localement sans nouvelle requête.
- Insère le texte non fiable avec
textContent. - Valide le protocole d’un lien fourni par une API avant d’affecter sa destination.
- Utilise
?.pour les données imbriquées manquantes et??lorsque zéro doit rester zéro. - Remplace les résultats pour une nouvelle recherche ; ajoute les résultats d’une autre page.
2.2 Mets en forme les dates et les montants pour les lecteurs
Les API renvoient des valeurs faciles à échanger pour les programmes. Les lecteurs ont besoin de dates, d’heures et de montants mis en forme selon leur langue et leur région. Sépare la valeur stockée du texte utilisé pour l’afficher.
Lire d’abord le format de date
"2026-03-05T14:30:00Z" désigne un instant : le 5 mars 2026 à 14 h 30 UTC. Le Z signifie UTC. new Date(...) le convertit en objet JavaScript Date. Une chaîne contenant uniquement une date, comme "2026-03-05", est interprétée comme minuit UTC ; une date et une heure sans décalage, comme "2026-03-05T14:30", sont interprétées comme une heure locale.
Un horodatage Unix compte le temps écoulé depuis le 1er janvier 1970, UTC. Les API comptent souvent en secondes, mais Date utilise les millisecondes. new Date(1772721000 * 1000) donne le même instant du 5 mars. Omettre la multiplication donne une date en janvier 1970. Lis la documentation de l’API pour identifier l’unité.
Choisir des paramètres régionaux et un fuseau horaire
const date = new Date("2026-03-05T14:30:00Z");
const dateFormat = new Intl.DateTimeFormat("en-US", {
dateStyle: "medium",
timeStyle: "short",
timeZone: "UTC",
});
dateFormat.format(date);
La sortie est « Mar 5, 2026, 2:30 PM ». Avec en-GB, elle est « 5 Mar 2026, 14:30 ». Les dates courtes donnent « 3/5/26 » en en-US, « 05/03/2026 » en en-GB et « 05.03.26 » en de-DE.
Les paramètres régionaux contrôlent la présentation ; le fuseau horaire détermine l’heure locale. Sans timeZone, l’outil de mise en forme utilise le fuseau de l’appareil. Cet instant correspond à 9 h 30 à New York, 15 h 30 à Amsterdam et 23 h 30 à Tokyo. Conserve et envoie les instants en UTC, puis convertis-les pour l’affichage. Une date du calendrier comme un anniversaire demande de l’attention : afficher minuit UTC dans un fuseau situé à l’ouest d’UTC peut donner le jour précédent.
Séparer la devise des paramètres régionaux
const priceFormat = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR",
});
priceFormat.format(1234.5);
Cela donne €1,234.50. Pour le même montant, de-DE avec EUR donne 1.234,50 € ; en-US avec USD donne $1,234.50 ; en-US avec JPY donne ¥1,235. JPY n’a pas d’unité monétaire divisionnaire : son affichage habituel ne comporte donc aucune décimale. Le choix des paramètres régionaux ne convertit pas les devises. Utilise le code de devise fourni avec le montant.
Certaines API de paiement envoient des unités divisionnaires sous forme d’entiers. Avec USD, 1999 cents représentent 19.99 dollars américains : divise par 100 avant la mise en forme. N’applique pas ce diviseur à JPY. Additionner des cents entiers donne 1999 + 2550 = 4549, ce qui est mis en forme comme $45.49. Cela évite le résultat bien connu du calcul décimal 0.1 + 0.2, qui vaut 0.30000000000000004.
Réutiliser l’outil de mise en forme
Crée une seule fois un outil de mise en forme pour une liste. Utilise undefined comme paramètres régionaux pour sélectionner ceux du navigateur par défaut ; navigator.language indique le code de langue préféré du navigateur. D’autres options mettent en forme 0.256 comme « 26% », ou 12.5 avec l’unité "kilometer-per-hour" comme « 12.5 km/h ». new Intl.RelativeTimeFormat("en", { numeric: "auto" }).format(-1, "day") donne « yesterday ». Les dates construites à la main comme « 03/05/2026 » restent ambiguës selon les régions.
Points clés
- Vérifie si les horodatages utilisent des secondes ou des millisecondes.
- Un fuseau horaire explicite rend prévisible l’affichage de la date et de l’heure.
- Les paramètres régionaux contrôlent la mise en forme ; la devise provient des données.
- Convertis les unités divisionnaires indiquées dans la documentation avant de mettre en forme un montant monétaire.
- Réutilise les objets de mise en forme
Intlpour toute une liste. - Les chaînes contenant uniquement une date sont interprétées en UTC et peuvent changer de jour lorsqu’elles sont affichées dans un autre fuseau.
2.3 Montre ce que fait la requête
Une requête a un cycle de vie visible : inactive, en chargement, puis réussie ou en erreur. Le succès peut contenir des données ou un résultat vide. La page doit expliquer chaque état pour que les lecteurs sachent s’ils doivent attendre, modifier une recherche ou réessayer.
Regrouper la préparation et la remise en état
Dans ce gestionnaire, getJSON vérifie le code d’état HTTP et analyse le corps, searchUrl construit l’URL de la requête et renderResults met la liste à jour. Le bouton et l’élément d’état existent déjà dans la page.
async function search(query) {
button.disabled = true;
status.textContent = "Loading…";
try {
const data = await getJSON(searchUrl(query));
renderResults(data.results);
status.textContent = data.results.length === 0 ? "No results." : "";
} catch (error) {
status.textContent = "Could not load results. Check your connection and try again.";
console.error(error);
} finally {
button.disabled = false;
}
}
La préparation a lieu avant l’attente. En cas de succès, le code affiche les résultats et gère un tableau vide. Le bloc catch remplace le message de chargement si une étape attendue échoue. finally rétablit le bouton dans les deux cas. Si la remise en état n’avait lieu qu’après un await réussi, un échec laisserait la commande désactivée.
Expliquer la cause utile
Une erreur HTTP possède un code d’état qui aide à formuler le message. Pour 404, indique que l’élément est introuvable. Pour 401, demande à l’utilisateur de se connecter ; pour 403, explique que l’accès n’est pas autorisé. Pour 429, demande-lui de patienter. Pour 5xx, explique que le service rencontre un problème et propose de réessayer plus tard.
Une TypeError provenant de fetch peut indiquer une panne réseau, une requête bloquée par CORS ou une URL incorrecte. JavaScript ne reçoit pas de diagnostic CORS détaillé et fiable ; examine la console du navigateur et l’onglet Réseau. Une SyntaxError provenant de json() indique du JSON invalide. L’annulation et les limites de durée produisent des erreurs comme AbortError et TimeoutError. Garde les détails techniques dans la console et indique aux lecteurs une action qu’ils peuvent comprendre.
Rendre les changements perceptibles
Utilise un élément d’état existant comme <p role="status"></p>. Ses changements sont annoncés aux lecteurs d’écran sans déplacer le focus. aria-live="polite" remplit un rôle similaire ; role="alert" convient aux erreurs urgentes. Un indicateur de chargement seul ne signale pas un résultat vide ou une requête échouée.
Un bouton Réessayer appelle à nouveau la fonction de chargement. Répéter sans modification des requêtes ayant reçu 400 ou 404 reproduit généralement le problème. Des pannes temporaires du réseau ou du service peuvent justifier une courte série limitée de nouvelles tentatives. L’attente exponentielle augmente la pause, par exemple 1 seconde, 2 secondes, puis 4 secondes. Respecte l’en-tête de réponse Retry-After ; il peut indiquer un délai en secondes ou une date HTTP. Évite de répéter automatiquement une requête de création qui a peut-être déjà réussi.
Si une actualisation échoue mais que les données précédentes sont encore utiles, laisse-les visibles avec une note comme « Résultats de 10 h 42 affichés. Actualisation impossible. » Ne laisse pas croire silencieusement que les anciens résultats sont à jour.
Tester les cas difficiles
Utilise les outils de développement pour ralentir la connexion, passer hors ligne et demander un chemin inexistant. Vérifie que le chargement apparaît rapidement, qu’une requête échouée le remplace, qu’un succès sans résultat a son propre message et que les commandes redeviennent utilisables.
Points clés
- Rends visibles le chargement, le succès sans résultat, le succès avec des données et les erreurs.
- Place la remise en état commune dans
finally. - Propose aux lecteurs une action utile et garde les détails techniques dans la console.
- Annonce les mises à jour d’état au moyen d’une région dynamique adaptée.
- Limite les nouvelles tentatives et respecte le délai demandé par le serveur.
2.4 Contrôle les requêtes simultanées et parallèles
Les requêtes peuvent durer plus longtemps que l’action qui les a lancées. Une réponse de recherche peut arriver après que le lecteur a saisi autre chose, et un service lent peut laisser une page attendre trop longtemps. Contrôle si les résultats sont encore pertinents, ainsi que la réussite de chaque requête.
Annuler le travail devenu inutile
Crée un AbortController, passe son signal à fetch, puis appelle abort() pour annuler la requête. L’annulation peut interrompre l’attente des en-têtes ou une lecture du corps en cours. L’erreur de rejet est normalement nommée "AbortError".
const controller = new AbortController();
const response = await fetch(url, { signal: controller.signal });
// A cancel button can call controller.abort().
const data = await response.json();
Gère les erreurs autour des deux attentes. Si ton code annule volontairement une recherche obsolète, termine silencieusement pour cette annulation attendue au lieu d’indiquer à l’utilisateur que le service a échoué.
fetch ne possède pas d’option timeout intégrée. Utilise un signal comme AbortSignal.timeout(5000) pour limiter la requête à 5 000 ms, soit 5 secondes de temps actif. Avant l’arrivée des en-têtes, la promesse est rejetée avec TimeoutError ; après leur arrivée, le délai peut interrompre la lecture du corps.
Empêcher les anciennes recherches de prendre le dessus
Une condition de concurrence se produit lorsque l’ordre d’achèvement modifie le résultat. Un lecteur saisit « ch », puis « chat ». Si la réponse pour « ch » arrive en dernier et est affichée, l’écran ne correspond plus à la saisie.
Une approche annule la requête précédente avant chaque nouvelle requête. Une autre attribue un numéro à chaque appel et ne laisse que le plus récent mettre la page à jour :
let latest = 0;
async function search(query) {
const request = ++latest;
try {
const data = await getJSON(searchUrl(query));
if (request !== latest) return;
renderResults(data.results);
} catch (error) {
if (request !== latest) return;
showError(error);
}
}
Cette vérification empêche aussi un ancien échec de remplacer un succès plus récent. Applique la même vérification de pertinence aux messages de chargement et à la remise en état des commandes lorsque les appels se chevauchent.
L’anti-rebond réduit le nombre d’appels lancés. Efface la minuterie précédente à chaque frappe et démarre-en une nouvelle, par exemple de 300 ms. Saisir rapidement « paris » lance alors une seule requête après la pause. L’anti-rebond économise des requêtes ; il n’empêche pas à lui seul une réponse à un appel précédent encore en cours d’arriver tardivement.
Décider ce qui peut s’exécuter ensemble
Des requêtes indépendantes peuvent être lancées ensemble :
const [user, posts] = await Promise.all([
getJSON(userUrl),
getJSON(postsUrl),
]);
Pour des durées de 300 ms et 500 ms, les deux prennent environ 500 ms au lieu d’environ 800 ms en séquence. Promise.all est rejetée dès que l’une des promesses fournies est rejetée, mais elle n’annule pas les autres opérations.
Utilise Promise.allSettled lorsque des résultats partiels sont utiles. Elle attend toutes les promesses fournies et indique chaque résultat sous la forme { status: "fulfilled", value } ou { status: "rejected", reason }. Un tableau de bord peut ainsi afficher les panneaux ayant réussi à côté de celui qui a échoué.
Les requêtes dépendantes doivent rester en séquence. Si une seconde URL nécessite un identifiant renvoyé par la première requête, attends cet identifiant avant de construire la seconde requête.
Points clés
- Passe un signal d’annulation avant d’appeler
abort(). - Intercepte les erreurs de récupération et de lecture du corps.
- Ignore les résultats et les erreurs obsolètes.
- L’anti-rebond réduit les appels ; une vérification de pertinence empêche les mises à jour obsolètes.
- Utilise
Promise.allpour des opérations indépendantes qui doivent toutes réussir. - Utilise
Promise.allSettledlorsque des résultats partiels sont utiles. - Attends les données nécessaires avant de lancer une requête dépendante.
3Lis des données entre origines et protège les identifiants
Une requête peut sembler correcte et pourtant échouer dans un navigateur parce que la page et l’API appartiennent à des origines différentes. Cette frontière est contrôlée conjointement par les règles du navigateur et les en-têtes de réponse du serveur. Tu identifieras l’origine, interpréteras les échecs des requêtes préliminaires et de CORS, et distingueras l’autorisation de lire une réponse de celle d’effectuer une action. Les identifiants nécessitent une décision distincte : tout ce qui est envoyé à un navigateur peut être examiné par son utilisateur.
3.1 Comprends la frontière des origines dans le navigateur
Une origine combine le schéma, l’hôte et le port d’une URL. Le chemin n’en fait pas partie. https://shop.example.com/cart et /help sur le même site partagent une origine. Passer à http://shop.example.com, https://api.example.com ou https://shop.example.com:8443 change l’origine. HTTPS utilise normalement le port 443.
Qui autorise la lecture de la réponse ?
La politique de même origine limite les ressources qu’un script de page peut lire. Pour une récupération depuis une autre origine, CORS permet au serveur de l’API d’accorder l’accès au moyen d’en-têtes de réponse. Une page sur https://notes.example.org qui appelle https://api.example.com/weather a besoin de l’autorisation de l’API pour lire la réponse.
Access-Control-Allow-Origin: https://notes.example.org accorde l’accès à cette origine. La valeur * autorise toutes les origines pour une requête sans identifiants. Si la réponse ne contient pas d’autorisation correspondante, le navigateur la cache à la page et fetch est rejeté avec une TypeError. La console fournit le diagnostic CORS ; JavaScript ne reçoit pas la raison détaillée.
Ajouter Access-Control-Allow-Origin à la requête JavaScript n’accorde pas d’autorisation. C’est un en-tête de réponse contrôlé par le serveur. Ajouter un en-tête de requête personnalisé peut au contraire provoquer une vérification préliminaire supplémentaire.
Pourquoi OPTIONS apparaît avant POST
Certaines requêtes vers une autre origine nécessitent une requête préliminaire. Le navigateur envoie d’abord OPTIONS, en indiquant la méthode prévue dans Access-Control-Request-Method et les noms des en-têtes non autorisés par défaut dans Access-Control-Request-Headers. Le serveur les autorise avec Access-Control-Allow-Methods et Access-Control-Allow-Headers, en plus de l’autorisation de l’origine.
Un GET, HEAD ou POST simple, avec seulement des en-têtes autorisés, peut éviter la requête préliminaire. Les types de contenu autorisés comprennent text/plain, application/x-www-form-urlencoded et multipart/form-data. Un POST JSON, un en-tête Authorization, PUT ou DELETE nécessite une requête préliminaire, sauf si une autorisation antérieure valide est en cache. Si la requête préliminaire est refusée, la requête réelle n’est pas envoyée.
Pour une requête simple, la requête réelle peut atteindre le serveur même si le navigateur bloque ensuite la lecture de sa réponse. CORS ne remplace donc pas l’autorisation côté serveur ni la vérification des entrées.
Les cookies ajoutent une exigence
La valeur par défaut credentials: "same-origin" n’envoie les cookies que pour les requêtes de même origine. credentials: "include" autorise également les cookies admissibles dans les requêtes vers d’autres origines. Les règles SameSite des cookies et les politiques relatives aux cookies tiers continuent de s’appliquer.
Pour permettre à JavaScript de lire une réponse associée à des identifiants, le serveur doit envoyer Access-Control-Allow-Credentials: true et nommer explicitement l’origine de la page. Access-Control-Allow-Origin: * ne fonctionne pas avec des identifiants. Ces en-têtes ne forcent pas un navigateur à envoyer un cookie qui serait autrement bloqué.
Diagnostiquer sans masquer le problème
mode: "no-cors" donne une réponse opaque avec l’état 0, sans corps ni en-têtes lisibles. Elle ne peut pas fournir de JSON à une page. Une requête qui fonctionne dans curl ne prouve pas non plus que CORS l’autorise dans le navigateur : les clients de terminal n’appliquent pas cette politique du navigateur.
Examine la console et l’onglet Réseau. Vérifie si la requête préliminaire a échoué ou si la réponse finale ne contenait pas l’autorisation nécessaire. Corrige la configuration des réponses de l’API ou fais passer l’appel par ton propre serveur. Pendant le développement, sers les pages depuis un serveur local : les pages file:// ont souvent des origines opaques. Un serveur local a toujours besoin d’une autorisation CORS lorsqu’il appelle une origine différente.
Points clés
- Une origine est constituée d’un schéma, d’un hôte et d’un port.
- Les en-têtes de réponse du serveur accordent l’autorisation de lecture entre origines.
- La requête préliminaire vérifie la méthode et les en-têtes prévus avant la requête réelle.
- CORS peut cacher une réponse après qu’une requête simple a déjà été traitée.
- Les réponses associées à des identifiants nécessitent une origine explicite et un en-tête d’autorisation des identifiants.
no-corsproduit une réponse opaque, et non du JSON lisible.
3.2 Garde les clés secrètes hors de la page
Une clé d’API identifie une application qui appelle une API, pour l’utilisation, les limites et la facturation. Un jeton d’accès accorde un accès pour un utilisateur ou une session. Toute personne possédant un identifiant utilisable peut être en mesure d’agir avec les droits associés : décide donc où le placer avant de l’ajouter à une requête.
Les en-têtes protègent l’emplacement, pas le secret vis-à-vis de l’utilisateur
Les fournisseurs peuvent exiger Authorization: Bearer <token>, X-API-Key: <key> ou un paramètre de requête comme api_key. Suis la documentation de l’API. Un en-tête évite de placer l’identifiant dans une URL complète qui peut se retrouver dans des journaux et des outils d’analyse. Un en-tête Authorization ou personnalisé dans un appel vers une autre origine déclenche normalement une requête préliminaire.
Un en-tête reste visible dans les outils de développement. Les visiteurs peuvent examiner le JavaScript qu’ils téléchargent et les requêtes qu’il envoie. Minifier le code ou cacher une valeur derrière une variable ne la rend pas secrète.
Suivre la clé dans une requête météo
Supposons que le code du navigateur appelle https://api.weather.example/v1/current?city=Lima&key=sk_live_4f9a2c. Toute personne qui ouvre l’onglet Réseau peut copier la clé et utiliser le quota du compte. Déplacer cette valeur dans une variable d’environnement utilisée lors de la compilation ne sert à rien si la compilation l’insère dans le JavaScript envoyé à la page.
Un secret conservé sur un serveur change le parcours :
- La page appelle son propre site à
/api/weather?city=Lima. - Le serveur de ce site ajoute le secret et contacte le fournisseur météo.
- Le serveur renvoie les données météo à la page sans inclure le secret dans la réponse.
Le serveur doit toujours contrôler l’accès à son point de terminaison et son utilisation. Conserver le secret du fournisseur sur un serveur ne rend pas inoffensive une utilisation publique illimitée.
Certains fournisseurs délivrent des clés pour navigateur destinées à être publiques. Applique les restrictions de domaine du fournisseur, limite les API autorisées et définis des quotas d’utilisation. N’utilise une clé de cette façon que si sa conception documentée le permet ; une clé serveur secrète ne devient pas une clé pour navigateur par l’ajout d’une restriction de domaine.
Réagir à une exposition
Ne place pas les fichiers d’identifiants sous contrôle de version, par exemple en indiquant .env dans .gitignore. Cela empêche que le fichier soit inclus dans un commit ; cela n’empêche pas une compilation côté client de publier une valeur intégrée au code. Si une clé est exposée, révoque-la et crée une clé de remplacement. La retirer du commit le plus récent laisse intacts l’historique antérieur et les éventuelles copies.
Protéger l’échange et réduire le gaspillage
Utilise HTTPS pour les appels d’API afin que les données et les identifiants soient chiffrés pendant leur transit. Un appel fetch d’une page HTTPS vers une API HTTP est bloqué comme contenu mixte. Le chiffrement n’empêche pas la personne qui utilise le navigateur de voir sa propre requête.
Une limite de requêtes plafonne l’utilisation, par exemple à 60 requêtes par minute. Les appels dépassant la limite peuvent renvoyer 429 Too Many Requests. Mets en cache les résultats appropriés, applique l’anti-rebond aux saisies de recherche et évite les appels en double. Si le serveur fournit Retry-After, respecte le délai indiqué au lieu de réessayer immédiatement à répétition.
La validation côté client facilite l’utilisation des formulaires, mais tout le monde peut appeler un point de terminaison sans passer par ton formulaire. Le serveur doit lui-même valider les requêtes et autoriser les actions. Lorsque tu affiches sa réponse, continue de traiter les chaînes comme du texte non fiable et insère-les avec textContent.
Points clés
- Le code et les requêtes envoyés au navigateur exposent tous les identifiants qu’ils contiennent.
- Une clé secrète doit rester sur le serveur qui appelle le fournisseur.
- Restreins les clés publiques pour navigateur par domaine, par API et par quota.
- Révoque une clé exposée ; la supprimer du code actuel ne suffit pas.
- HTTPS chiffre les données en transit, tandis que le serveur doit toujours valider et autoriser les requêtes.
4Conserve de petites quantités de données d’état dans le navigateur
Un paramètre ou un brouillon peut survivre à un rechargement sans nouvelle requête au serveur. Le stockage du navigateur rend cela pratique, mais ses valeurs sont des chaînes de caractères et leur durée de vie dépend du stockage choisi. Tu enregistreras et restaureras de petites quantités de données d’état, valideras les anciennes données avant de les utiliser et donneras une durée d’expiration aux résultats d’API mis en cache. Tu décideras aussi quelles données doivent être conservées ailleurs, car le stockage local n’est ni un coffre-fort à secrets ni l’unique copie sûre d’un travail important.
4.1 Enregistre des chaînes et restaure leurs types
Web Storage propose deux espaces de stockage clé-valeur : localStorage et sessionStorage. Ils utilisent les mêmes méthodes : le choix principal porte donc sur la durée de conservation des données et les onglets qui doivent les partager.
Choisir la durée de vie
| Stockage | Durée de vie | Partage |
|---|---|---|
localStorage | Survit à la fermeture de l’onglet et du navigateur jusqu’à suppression ou effacement | Partagé par les pages de la même origine |
sessionStorage | Survit aux rechargements pendant la session de page de l’onglet | Distinct pour chaque onglet et chaque origine |
Fermer l’onglet met fin à son stockage de session. Une page nouvellement ouverte avec un élément déclencheur peut commencer avec une copie du stockage de session de cet élément, mais les modifications ultérieures restent distinctes. N’utilise pas le stockage de session pour garder des informations secrètes vis-à-vis des scripts.
Le stockage dépend des origines. https://app.example.com ne peut pas partager son stockage avec http://app.example.com. Les chemins d’une même origine le partagent : un préfixe comme "notes-app:settings" aide donc à distinguer les clés de plusieurs applications.
Utiliser les méthodes de stockage
localStorage.setItem("notes-app:theme", "dark");
const theme = localStorage.getItem("notes-app:theme");
localStorage.removeItem("notes-app:theme");
setItem crée ou écrase une entrée. getItem renvoie sa valeur sous forme de chaîne ou null si elle est absente. removeItem supprime une entrée. clear() supprime toutes les entrées de cet espace de stockage pour l’origine, ce qui peut affecter d’autres fonctionnalités du même site. length et key(index) permettent d’examiner les clés.
Utilise ces méthodes plutôt que des affectations de propriétés comme localStorage.theme = "dark". Des clés comme "length" ou "key" peuvent entrer en conflit avec des membres intégrés lorsqu’on y accède comme à des propriétés.
Convertir les valeurs explicitement
Après localStorage.setItem("count", 5), la lecture donne "5". Ajouter directement 1 produit "51". Number(localStorage.getItem("count")) + 1 produit 6.
Un booléen stocké présente un piège similaire. setItem("darkMode", false) stocke "false", et une chaîne non vide est une valeur vraie dans un contexte booléen. Lis avec localStorage.getItem("darkMode") === "true" lorsque ce sont les deux chaînes stockées attendues.
Les objets et les tableaux nécessitent JSON :
localStorage.setItem("settings", JSON.stringify({
theme: "dark",
fontSize: 18,
}));
const settings = JSON.parse(localStorage.getItem("settings"))
?? { theme: "light", fontSize: 16 };
Sans sérialisation, un objet ordinaire devient "[object Object]". JSON.parse(null) donne null, donc la valeur par défaut couvre le cas d’une entrée manquante. Une chaîne stockée mal formée nécessite toujours try/catch, et les données analysées doivent être vérifiées avant utilisation pour s’assurer qu’elles ont la bonne structure.
Limiter le travail
Les appels à Web Storage sont synchrones : JavaScript attend chacun d’eux sur le thread principal. Utilise-le pour des paramètres, un brouillon ou une courte liste, pas pour de grandes collections ou des fichiers. IndexedDB fournit un stockage asynchrone pour des données structurées plus volumineuses.
Les navigateurs actuels autorisent généralement environ 5 Mio dans chaque espace Web Storage par origine. Un stockage plein peut amener setItem à lever QuotaExceededError ; l’accès peut aussi échouer en raison des paramètres de confidentialité du navigateur. Gère l’échec sans empêcher le reste de l’application de fonctionner. Les outils de développement affichent les espaces de stockage dans l’onglet Application de Chrome et Edge ou dans l’onglet Stockage de Firefox, où la suppression d’entrées aide à tester les premières visites.
Points clés
- Choisis
localStoragepour les paramètres partagés persistants etsessionStoragepour l’état propre à la session d’un onglet. - Les espaces de stockage sont séparés par origine.
getItemrenvoie une chaîne de caractères ounull.- Sérialise les objets avec JSON et restaure leurs types à la lecture.
- Gère les échecs de stockage et limite la taille des écritures synchrones.
4.2 Restaure l’état et fais expirer les données en cache
Une application charge généralement au démarrage et enregistre à chaque modification. Lis une liste enregistrée à l’ouverture de la page, affiche-la et enregistre la liste mise à jour après une modification. Le stockage du navigateur est une copie pratique : il peut être absent, endommagé, obsolète ou effacé.
Valider avant de restaurer
Cette fonction de chargement attend un tableau de chaînes enregistré :
function loadTodos() {
try {
const value = JSON.parse(localStorage.getItem("todos"));
if (Array.isArray(value) && value.every(item => typeof item === "string")) {
return value;
}
} catch {
// Continue with an empty list if reading or parsing fails.
}
return [];
}
JSON.parse seul ne prouve pas que la valeur est un tableau ni que ses éléments conviennent à l’application. Une valeur JSON valide comme 42 n’a tout de même pas la bonne structure. Une valeur comportant une version comme { version: 2, todos: [...] } permet au code plus récent de reconnaître les anciens formats et de les convertir ou de restaurer une valeur par défaut.
Enregistre la liste en mémoire avec localStorage.setItem("todos", JSON.stringify(todos)) après chaque modification. Intercepte aussi les échecs d’écriture ; une page doit pouvoir continuer à fonctionner même si elle ne peut pas conserver l’état pour le prochain rechargement. Un brouillon de formulaire propre à une seule visite peut utiliser sessionStorage.
Horodater les réponses en cache
localStorage.setItem("weather", JSON.stringify({
savedAt: Date.now(),
data,
}));
Lors d’un chargement ultérieur, vérifie d’abord la structure et l’horodatage de l’objet en cache. Son âge est Date.now() - savedAt. Ne l’utilise que tant que cet âge est inférieur à 10 * 60 * 1000, soit 600 000 ms. Une valeur enregistrée à 10:00:00 a 450 000 ms à 10:07:30 et peut être utilisée. À 10:12:00, elle a 720 000 ms : récupère donc une nouvelle valeur. À exactement 600 000 ms, elle est expirée selon cette règle.
L’expiration relève de la logique de l’application : localStorage ne supprime pas une entrée lorsque ton intervalle de fraîcheur prend fin. Rejette un horodatage manquant ou invalide au lieu de considérer comme récente une donnée d’âge inconnu. Tu peux laisser des données périmées visibles lorsqu’une actualisation échoue si elles sont indiquées comme anciennes.
Synchroniser les autres onglets
Lorsqu’un onglet modifie localStorage, les autres onglets de la même origine reçoivent un événement storage. L’onglet qui écrit ne reçoit pas son propre événement. L’événement expose key, oldValue, newValue et url.
window.addEventListener("storage", (event) => {
if (event.key === "theme") applyTheme(event.newValue);
});
Applique aussi immédiatement le thème dans l’onglet qui écrit. Gère null lorsqu’une clé est supprimée. Un événement de stockage ne remplace pas la mise à jour de l’état de ta propre page.
Décider de ce qui doit être conservé ailleurs
Ne place pas de mots de passe, de numéros de carte de paiement ou de clés d’API secrètes dans Web Storage. Les scripts de l’origine peuvent le lire, y compris le code tiers et les scripts injectés. Efface les données personnelles concernées à la déconnexion sur les appareils partagés. Conserve les travaux importants sur un serveur ou propose leur exportation, car les utilisateurs peuvent effacer les données du site et les sessions privées les suppriment.
Les cookies sont différents : les requêtes correspondantes les envoient au serveur, et les scripts de la page ne peuvent pas lire les cookies HttpOnly. Ils sont petits, environ 4 Ko chacun. Web Storage reste dans le navigateur et peut être lu par les scripts. IndexedDB convient aux données structurées plus volumineuses grâce à une API asynchrone.
Points clés
- Valide les données analysées et utilise une solution de repli si elles sont absentes ou endommagées.
- La fraîcheur du cache dépend d’un horodatage et d’une limite d’âge définie par l’application.
- L’événement
storageatteint les autres onglets de la même origine, pas celui qui écrit. - Ne conserve pas de secrets ni de données irremplaçables dans Web Storage.
5Utilise les fonctionnalités de localisation et de presse-papiers
Les API du navigateur donnent à une page accès à des fonctionnalités comme la localisation et le presse-papiers. Leur disponibilité dépend du navigateur, du contexte de sécurité de la page et des choix de l’utilisateur. Tu détecteras une fonctionnalité avant de l’appeler, demanderas l’autorisation à un moment approprié et géreras le succès ou le refus. Une interaction complète comprend un retour visible et un autre moyen de terminer la tâche, comme saisir une ville ou copier au clavier un texte sélectionné.
5.1 Demande une position avec une solution de repli
La géolocalisation est une API du navigateur : une fonctionnalité fournie par le navigateur, distincte du langage JavaScript. Comme d’autres fonctionnalités de l’appareil, elle peut être indisponible ou refusée. Une page météo doit continuer à fonctionner lorsqu’un lecteur choisit de saisir une ville.
Vérifier la fonctionnalité et le contexte
Détecte la fonctionnalité elle-même avec "geolocation" in navigator. Vérifier le nom d’un navigateur est moins fiable : les versions et les paramètres modifient ce qui est disponible. La géolocalisation nécessite un contexte sécurisé, normalement HTTPS ; http://localhost convient aussi pour le développement. window.isSecureContext indique si la page actuelle remplit cette condition. Le simple HTTP sur l’adresse réseau d’un autre appareil n’est pas équivalent à localhost.
Explique pourquoi la position est utile et demande-la lorsque le lecteur clique sur « Utiliser ma position ». Le navigateur gère la demande d’autorisation. Une personne peut l’autoriser ou la bloquer, et un refus antérieur peut faire échouer un appel ultérieur sans nouvelle demande. L’utilisateur peut modifier cette décision dans les paramètres du site.
Lire le résultat de la fonction de rappel
navigator.geolocation.getCurrentPosition(success, error, options) utilise des fonctions de rappel. En cas de succès, position.coords contient la latitude et la longitude en degrés décimaux et accuracy en mètres. La précision correspond à un rayon d’incertitude estimé, pas à une précision décimale supplémentaire. En cas d’échec, le code 1 signifie que l’autorisation est refusée, 2 que la position est indisponible et 3 que le délai a expiré.
Les options contrôlent la tentative :
enableHighAccuracy: demande une meilleure précision ; valeur par défautfalse.timeout: limite d’attente en millisecondes ; valeur par défautInfinity.maximumAge: âge maximal d’une position en cache acceptable ; valeur par défaut0.
Utilise un délai fini pour que la page puisse sortir de l’attente. watchPosition observe les mises à jour au fil du temps et renvoie un identifiant ; passe cet identifiant à clearWatch lorsque le suivi doit s’arrêter.
Encapsuler les fonctions de rappel pour utiliser await
function getPosition(options) {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject, options);
});
}
async function useLocation() {
if (!("geolocation" in navigator)) {
showCityInput();
return;
}
try {
const { coords } = await getPosition({ timeout: 10000 });
const url = new URL("https://api.example.com/weather");
url.searchParams.set("lat", coords.latitude.toFixed(2));
url.searchParams.set("lon", coords.longitude.toFixed(2));
await loadWeather(url);
} catch {
showCityInput();
}
}
Ici, showCityInput affiche la commande de saisie manuelle et loadWeather demande et affiche la météo. Relie useLocation au bouton de localisation. Le bloc catch couvre l’échec de localisation et la requête météo ; dans les deux cas, la saisie manuelle reste disponible.
Ne demander que la précision utile
Une position de latitude 52.3676, de longitude 4.9041 et de précision 35 a un rayon estimé d’environ 35 m. Arrondir à 52.37 et 4.90 réduit la précision envoyée au service météo. Un intervalle de latitude de 0,01° représente environ 1,1 km ; l’espacement des longitudes varie selon la latitude. Cette précision régionale convient à une prévision sans partager les coordonnées les plus détaillées.
Lorsque l’API Permissions est disponible, navigator.permissions.query({ name: "geolocation" }) indique "granted", "denied" ou "prompt". Détecte et gère aussi cette API. Son état aide à adapter l’interface, mais ne remplace pas la gestion des erreurs de l’appel de localisation.
Points clés
- Détecte la géolocalisation et utilise un contexte sécurisé.
- Demande la position après une action explicite de l’utilisateur et en indiquant pourquoi.
- La latitude et la longitude sont exprimées en degrés ; la précision est exprimée en mètres.
- Définis un délai fini et propose une saisie manuelle en cas d’échec.
- N’envoie que la précision de localisation nécessaire à la fonctionnalité.
- L’état de l’autorisation ne garantit pas une position exploitable.
5.2 Copie du texte et découvre une autre API du navigateur
L’API du presse-papiers permet à une page de copier du texte sans demander au lecteur de le sélectionner d’abord. Comme la géolocalisation, elle nécessite des vérifications de disponibilité, une action appropriée de l’utilisateur, une gestion des erreurs et une solution de repli.
Copier pendant le clic
navigator.clipboard.writeText(text) renvoie une promesse. Attends qu’elle soit tenue avant d’annoncer le succès. Un contexte sécurisé est obligatoire et une opération refusée peut entraîner un rejet avec NotAllowedError. Appelle cette méthode directement depuis un gestionnaire de clic : Firefox et Safari exigent une interaction récente de l’utilisateur, tandis que les exigences de Chromium peuvent aussi dépendre de l’autorisation d’écriture dans le presse-papiers.
copyButton.addEventListener("click", async () => {
try {
if (!navigator.clipboard?.writeText) {
throw new Error("Copy unavailable");
}
await navigator.clipboard.writeText(codeField.value);
copyButton.textContent = "Copied!";
} catch {
codeField.focus();
codeField.select();
copyButton.textContent = "Copy selected text: Ctrl+C / Cmd+C";
}
setTimeout(() => {
copyButton.textContent = "Copy";
}, 2000);
});
codeField est un champ de saisie ou une zone de texte et copyButton est le bouton de la page. Si la copie échoue, la sélection du texte permet de passer par le clavier : Ctrl+C sur de nombreux systèmes ou Cmd+C sur macOS. Le libellé redevient « Copy » après 2 000 ms. N’affiche jamais « Copied! » avant que la promesse soit tenue.
La lecture utilise navigator.clipboard.readText() et fait l’objet de contrôles plus stricts, car un presse-papiers peut contenir des données privées provenant d’autres applications. Un navigateur peut exiger une autorisation ou afficher une demande de collage. L’autorisation d’écrire ne garantit pas l’autorisation de lire.
Considérer la connectivité comme un indice
navigator.onLine et les événements online et offline de la fenêtre aident à afficher une bannière de connexion. Ils ne permettent pas de savoir si ton API est accessible. Un appareil peut avoir une connexion réseau alors que le serveur de l’API est en panne ou inaccessible.
window.addEventListener("offline", () => {
status.textContent = "You are offline.";
});
Continue de gérer les erreurs autour de fetch même lorsque navigator.onLine est vrai. Utilise une région dynamique adaptée pour le message d’état.
Lire une recherche partageable
L’API URL lit la chaîne de requête de la page elle-même et construit aussi des URL d’API. Sur https://books.example.org/search?q=dune, new URL(location.href).searchParams.get("q") renvoie "dune". Lis cette valeur au chargement pour restaurer une recherche depuis un lien partagé. Un paramètre manquant renvoie null : décide donc de ce que l’écran initial doit afficher dans ce cas.
Utiliser une méthode d’apprentissage
Pour une autre API du navigateur, lis sa syntaxe, ses règles de contexte sécurisé et d’autorisation, son tableau de compatibilité et son statut Baseline sur MDN. Détecte ensuite la fonctionnalité, appelle-la depuis une action de l’utilisateur lorsque c’est nécessaire, traite sa promesse ou ses fonctions de rappel et propose une alternative si elle est absente ou refusée.
L’API Notifications affiche des notifications système après autorisation ; Web Share ouvre le menu de partage d’un appareil lorsqu’il est pris en charge ; Canvas dessine des graphismes ; les API multimédias contrôlent l’audio et la vidéo. Une API de cartographie tierce peut ajouter une bibliothèque et une clé de fournisseur. Ses identifiants suivent les mêmes règles concernant les clés secrètes que ceux de tout autre service. Tester un navigateur sur localhost ne prouve pas qu’un autre appareil ou navigateur dispose de la même prise en charge et du même contexte.
Points clés
- Attends
writeTextavant d’annoncer que la copie a réussi. - Prévois une solution de copie au clavier si l’accès au presse-papiers échoue.
- La lecture du presse-papiers obéit à des règles d’autorisation distinctes et plus strictes.
- L’état en ligne ne garantit pas que l’API est accessible.
- Utilise les paramètres d’URL pour restaurer une recherche partageable.
- Vérifie la compatibilité, détecte les fonctionnalités et gère les refus pour chaque API du navigateur.
Fetch et API du navigateur : exemples
1Construis et mets à jour une liste de lecture
14 étapes
- 1IntroductionSuis un échange
Une page de liste de lecture doit charger des livres et ajouter une note sur l’un d’eux. La page est le client ; l’API est le serveur. Chaque échange comprend une requête qui décrit l’action et une réponse qui décrit son résultat.
Nous allons d’abord lire l’échange, puis relier les deux étapes asynchrones du chargement JSON et enfin soumettre une modification. La réponse du serveur détermine ce que la page peut afficher ensuite en toute sécurité.
- 2ExempleLis la ressource et les filtres
La page demande
GET https://api.example.com/books?author=Le%20Guin&limit=5.GETdemande une lecture./booksdésigne la ressource. La requête filtre par auteur et limite le nombre de résultats.%20représente l’espace dans « Le Guin ». La documentation de l’API détermine ces noms de paramètres ; la page ne peut pas choisir un autre nom et s’attendre à ce que le service le comprenne. - 3Point cléDistingue le code d’état de la connexion
Une réponse peut indiquer
200 OKavec un livre ou404 Not Foundavec une erreur. Les deux prouvent qu’un serveur a répondu. Une erreur de connexion ne fournit aucun code d’état HTTP à la page.Examine l’onglet Réseau pour voir l’URL complète, la méthode, le code d’état, les en-têtes et le corps. Si l’API a renvoyé le JSON attendu, examine ensuite le code qui le lit ou l’affiche.
- 4DéfiChoisis une méthode pour une modification
Une note existe déjà. La page doit modifier uniquement son champ
donetout en conservant son texte. Quelle méthode HTTP convient à cette opération et pourquoiGETserait-elle incorrecte ?---reveal---
Utilise
PATCHpour la mise à jour partielle.GETest une méthode de lecture sûre et ne doit pas servir à demander une modification de données.PUTdécrirait un remplacement complet et pourrait réinitialiser les champs omis du corps. - 5ExplicationAttends la réponse
Commence par
const response = await fetch(url). Cela attend l’arrivée des en-têtes de réponse et fournit un objetResponse, pas les livres analysés.La réponse peut tout de même être une erreur HTTP. La promesse de
fetchest tenue pour un404parce qu’une réponse existe. Vérifieresponse.okavant de considérer que l’opération a réussi ; cette propriété est vraie pour les codes d’état de200à299inclus. - 6ExempleVérifie et lis le corps
Continue dans la fonction asynchrone :
if (!response.ok) { throw new Error(`HTTP error ${response.status}`); } const data = await response.json();La seconde attente lit et analyse le corps.
dataest maintenant une valeur JavaScript. Un bloctry/catchexterne peut gérer à la fois l’erreur de code d’état levée ici et les échecs de récupération ou d’analyse du corps. - 7ExempleTrouve le tableau imbriqué
Supposons que le corps soit
{"results":[{"title":"Dune"}],"total":1}.La première étape,
data.results, donne accès au tableau.[0]donne accès à son premier objet..titledonne"Dune". Une fonction de rendu doit recevoirdata.results, pas tout l’objet englobant. L’aperçu de la réponse dans l’onglet Réseau est utile lorsque la structure de l’API diffère de celle attendue par la page. - 8DéfiDiagnostique la valeur manquante
Le code utilise
const data = response.json()puis essaiedata.results[0]. Le corps est bien du JSON valide contenant un tableauresults. Que manque-t-il ?---reveal---
Attends le corps :
const data = await response.json(). Sans cette attente,dataest une promesse et ne possède pas de propriétéresults. Le premierawait fetch(...)n’a pas attendu aussi l’analyse JSON. - 9ConseilPréserve la ponctuation dans une recherche
Construis les paramètres de requête avec l’API URL :
const url = new URL("https://api.example.com/search"); url.searchParams.set("q", "rock & roll");La valeur devient
rock+%26+roll. L’esperluette reste dans l’expression recherchée au lieu de séparer la requête. Réutilise la réponse analysée après le chargement : appeler une seconde méthode de lecture du corps sur la même réponse échoue, car le corps a été consommé. - 10ExemplePrépare une soumission JSON
Pour créer une note, sérialise les champs et indique leur format :
const response = await fetch("https://api.example.com/notes", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ title: "Read", done: false }), });La méthode demande une création, l’en-tête déclare le format JSON et le corps contient du texte JSON plutôt qu’un objet ordinaire.
- 11LienUtilise l’enregistrement stocké
Le serveur peut renvoyer
201 Createdavec{"id":31,"title":"Read","done":false}. Ajoute cet enregistrement renvoyé à l’état de la page. Son identifiant permet à une action ultérieure d’appeler/notes/31.Pour un formulaire avec des fichiers, passe
FormDataau lieu de JSON et laisse le navigateur définir son délimiteur multipart. Une requêteGETne peut pas transporter de corps avecfetch; les champs de recherche vont dans la chaîne de requête. - 12DéfiGère un succès sans corps
La suppression d’une note enregistrée renvoie
204. Le code vérifieresponse.ok, puis appelleresponse.json()et affiche une erreur. La suppression a-t-elle nécessairement échoué et que faut-il changer ?---reveal---
Non :
204indique une opération réussie sans corps. Ignore l’analyse JSON pour ce code d’état et mets la page à jour après l’avoir vérifié. L’échec de l’analyse vient de la tentative de lecture d’un contenu vide, pas d’une preuve que la suppression a échoué. - 13DéfiExamine un processus complet de soumission
Un bouton d’enregistrement peut recevoir deux clics pendant l’exécution d’un
POST. Une réponse réussie fournit un nouvel identifiant. Nomme les deux comportements de la page qui empêchent un doublon accidentel et conservent cet identifiant.---reveal---
Désactive le bouton pendant la requête et réactive-le dans
finally. En cas de succès, mets la page à jour à partir de l’enregistrement renvoyé, y compris son identifiant. Le bouton empêche les clics répétés ; le résultat du serveur fournit des valeurs qui n’existaient pas dans les données soumises. - 14RécapitulatifVérifie l’échange à chaque étape
Lorsqu’une requête ne fonctionne pas comme prévu, examine l’opération dans l’ordre : l’URL et la méthode documentées, le code d’état réel, la méthode choisie pour lire le corps et la structure des données transmises à la page.
Pour une écriture, vérifie aussi le type de contenu et le corps sérialisé. Un succès sans contenu ne nécessite pas de lecture JSON. Une réponse à une création doit fournir l’enregistrement sauvegardé utilisé pour la prochaine modification ou suppression.
2Construis une page de recherche qui reste à jour
18 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionGarde l’écran cohérent avec la recherche
- 2ExempleRemplace la liste précédente
- 3Point cléDistingue zéro des données manquantes
- 4DéfiTraite les textes et les liens externes
- 5ExempleLis l’unité de temps
- 6ExplicationChoisis le fuseau d’affichage
- 7ExempleMets en forme les unités divisionnaires documentées
- 8DéfiSépare les paramètres régionaux de la valeur
- 9ExplicationCommence par rendre l’attente visible
- 10ExempleTermine tous les parcours
- 11DéfiReconnais une recherche réussie sans résultat
- 12ConseilAttends avant de réessayer après un échec temporaire
- 13ExempleObserve l’ordre d’achèvement
- 14ExempleAnnule une requête obsolète
- 15LienRéduis les appels pendant la saisie
- 16DéfiChoisis un succès partiel
- 17DéfiProtège toute l’interaction en cours
- 18RécapitulatifTeste l’interface avec des réponses imparfaites
3Diagnostique un appel d’API entre origines
10 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionDistingue deux questions d’autorisation
- 2ExempleCompare les origines complètes
- 3ExplicationLis l’autorisation du serveur
- 4ExempleSuis d’abord la requête préliminaire
- 5DéfiExplique un succès limité au terminal
- 6ExempleTrouve la clé exposée
- 7LienDéplace la frontière du secret
- 8DéfiDistingue le transport du secret
- 9DéfiVérifie les cookies et les réponses lisibles
- 10RécapitulatifDiagnostique la frontière en échec
4Restaure une liste enregistrée sans bloquer la page
12 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionConserve une copie locale pratique
- 2ExplicationChoisis ce qui doit persister
- 3ExempleConserve un tableau sous forme de texte
- 4DéfiRestaure le type attendu
- 5ConseilGère une écriture qui dépasse l’espace disponible
- 6ExempleNe te limite pas à vérifier la syntaxe JSON
- 7ExempleAssocie une heure au cache
- 8DéfiCalcule si le cache est encore frais
- 9LienSuis un thème entre les onglets
- 10Point cléProtège les données importantes
- 11DéfiGère un ancien format enregistré
- 12RécapitulatifTeste une première visite et une visite ultérieure
5Ajoute des boutons de localisation et de copie utiles
13 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionRends l’action compréhensible
- 2ExplicationVérifie le contexte et la fonctionnalité
- 3ConseilFais la demande lorsque la fonctionnalité est utile
- 4ExempleDéfinis une attente limitée
- 5ExempleNe lis que la précision utile
- 6DéfiGère un refus
- 7ExempleÉcris pendant le clic
- 8Point cléAttends avant d’annoncer la copie
- 9DéfiConsidère un signal de connexion comme un indice
- 10LienRestaure une recherche depuis son lien
- 11ConseilVérifie une autre fonctionnalité du navigateur
- 12DéfiExamine les deux boutons ensemble
- 13RécapitulatifTeste aussi les choix de la personne
Fetch et API du navigateur : QCM
Série 1 : Requêtes, résultats et fonctionnalités du navigateur10 Questions Pratiques
Question 1 sur 10
403. Que dit ce code à la page ?Afficher la réponseMasquer la réponse
403 signifie que le serveur a compris la requête et refuse de la satisfaire. Elle ne prouve pas que l’utilisateur a fourni des identifiants valides ni qu’une connexion résoudra le refus. Une connexion réseau échouée ne fournirait pas de code d’état HTTP lisible par la page.Question 2 sur 10
200 avec {"items":[{"name":"Cedar"}]}. Quelle affectation stocke le nom du premier élément après const response = await fetch(url) ?Afficher la réponseMasquer la réponse
json() lise et analyse le corps, puis suis la propriété externe items jusqu’au premier objet du tableau. Appeler json() sans await laisse une promesse qui ne possède pas de tableau items. La lecture avec text() donne une chaîne, pas l’objet analysé nécessaire pour accéder aux propriétés.Question 3 sur 10
body doit-il recevoir lors de l’envoi de { label: "Read" } ?Afficher la réponseMasquer la réponse
JSON.stringify convertit l’objet en texte JSON valide pour le corps de la requête. Convertir un objet ordinaire avec String ou toString() produit "[object Object]", que le point de terminaison JSON ne peut pas analyser. La requête nécessite aussi la méthode documentée et un en-tête de type de contenu JSON.Question 4 sur 10
{ remaining: 0, owner: null }. Comment la page peut-elle afficher le nombre restant tout en utilisant "Unknown" pour le nom du propriétaire manquant ?Afficher la réponseMasquer la réponse
name depuis null. Utiliser || pour le nombre remplace zéro, car zéro est une valeur fausse dans un contexte booléen. Une valeur de repli après data.owner.name ne peut pas aider si l’accès à name a déjà levé une erreur.Question 5 sur 10
amount: 3785, currency: "USD" représente des unités divisionnaires entières. Quel nombre faut-il passer à l’outil de mise en forme monétaire ?Afficher la réponseMasquer la réponse
3785 afficherait un montant 100 fois trop élevé. Intl.NumberFormat met en forme le nombre reçu ; il ne déduit pas qu’un montant d’API est exprimé en cents.Question 6 sur 10
Afficher la réponseMasquer la réponse
finally s’exécute après l’opération protégée, qu’elle réussisse ou lève une exception : c’est donc le bon endroit pour la remise en état nécessaire dans les deux cas. Placer la réinitialisation uniquement dans catch oublie le succès ; la laisser après l’affichage oublie l’échec. Une minuterie réinitialiserait les commandes sans savoir si la requête est terminée.Question 7 sur 10
https://studio.example.org/edit. Quelle est son origine ?Afficher la réponseMasquer la réponse
/edit désigne une ressource dans l’origine et ne fait pas partie de l’origine elle-même. Passer le schéma à HTTP créerait une origine différente, même avec le même hôte.Question 8 sur 10
Afficher la réponseMasquer la réponse
Question 9 sur 10
localStorage.setItem("visits", 8), quelle est la valeur de localStorage.getItem("visits") + 1 ?Afficher la réponseMasquer la réponse
"8" : + 1 effectue donc une concaténation de chaînes et donne "81". Il ne restaure pas le type numérique passé à setItem. Convertis la chaîne stockée avec Number avant l’addition si le résultat attendu est le nombre 9.Question 10 sur 10
1. Quelle réponse à l’utilisateur convient à cet échec ?Afficher la réponseMasquer la réponse
1 signifie que l’autorisation a été refusée : propose donc un autre moyen d’indiquer la position. L’expiration du délai correspond au code 3 et n’explique pas cet échec. Des demandes répétées ne peuvent pas imposer l’autorisation ; un refus mémorisé peut obliger l’utilisateur à modifier les paramètres du site dans le navigateur.Série 2 : Suis les données dans l’interface10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
fetch renvoie un objet Response avec le code d’état 502. Le code possède un gestionnaire catch mais ne vérifie jamais response.ok. Pourquoi son message d’erreur HTTP pourrait-il ne jamais apparaître ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
204 en cas de succès. Que doit faire la page avant de tenter d’analyser du JSON ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Promise.all devrait-elle prendre ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
POST JSON avec Content-Type: application/json. Aucune autorisation de requête préliminaire n’est en cache. Que doit vérifier le navigateur avant d’envoyer ce POST ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
http://localhost, mais sa fonctionnalité de localisation est absente lorsqu’elle est ouverte sur un téléphone à une adresse réseau HTTP. Elle cesse aussi de fonctionner lorsque les utilisateurs sur ordinateur refusent la localisation. Quelle conception résout ces deux problèmes ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
navigator.clipboard.writeText(text). À quel moment doit-il afficher « Copié ! » ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 3 : Débogue les requêtes, le stockage et les autorisations10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
PUT /profiles/29 remplace le profil. Qu’implique l’idempotence lorsque la même requête complète est envoyée deux fois ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
new Date et affiche janvier 1970. Quelle conversion doit précéder la mise en forme de la date ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
503 avec Retry-After: 12. Quel comportement indique l’état et permet de réessayer ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
if (localStorage.getItem("compact")). Le texte stocké est "false", mais le mode compact s’active. Pourquoi ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
-12.0464, la longitude -77.0428 et la précision 80. Que décrit 80 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
https://recipes.example.org/search?q=green+tea lit new URL(location.href).searchParams.get("q"). Quelle valeur obtient-elle ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 4 : Conçois des fonctionnalités d’API fiables10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
429. Que signifie ce code d’état ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
<b>, un lien javascript: et remaining: 0. La page doit afficher le titre littéralement, n’autoriser que les liens web ordinaires et conserver le nombre. Quel plan de rendu répond aux trois besoins ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Intl.DateTimeFormat, des paramètres régionaux en-US fixes mais sans option timeZone. Les heures affichées diffèrent. Qu’est-ce qui explique cette différence ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
PATCH JSON vers une autre origine utilise credentials: "include". La requête préliminaire l’autorise. La réponse finale utilise un caractère générique pour l’origine et autorise les identifiants, si bien que JavaScript ne peut pas la lire. Le serveur suppose aussi que CORS rend les vérifications des utilisateurs inutiles. Quelles règles de réponse et d’accès corrigent cette conception ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
.map. Certains utilisateurs ont du JSON valide {"version":1,"items":[]} laissé par un ancien code, et d’autres ont du texte endommagé. Quel plan de restauration gère les deux cas ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
navigator.onLine === true, mais un appel d’API est rejeté. Que doit en déduire la page sur la connectivité et que doit-elle gérer ensuite ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Tu bloques sur ton propre exercice ? Aide aux Devoirs
Mots-Clés
A
AbortController
AbortSignal
AbortSignal.timeout(4000) limite une requête à quatre secondes de temps actif.Activation utilisateur
Anti-rebond
API du presse-papiers
API web
Attente exponentielle
Autorisation
B
Baseline
C
Cache
Chaînage optionnel
?. est null ou undefined, et renvoie undefined.book.author?.name de gérer un livre dont l’objet auteur est absent de la réponse.Clé d’API
Coalescence des nuls
?? uniquement lorsque la valeur à gauche est null ou undefined, en préservant les zéros valides.Code d’état
201 indique à la page que le serveur a créé une ressource en réponse à la requête.Condition de concurrence
Contenu mixte
Contexte sécurisé
Corps de réponse
Corps de requête
D
Délimiteur multipart
Détection de fonctionnalités
"geolocation" in navigator détermine si la page peut proposer la localisation de l’appareil.E
En-tête
Content-Type indique au programme destinataire que le corps associé contient du JSON.Encodage d’URL
Erreur d’analyse syntaxique
204 vide provoque une erreur d’analyse JSON même si le serveur a terminé l’opération avec succès.Expiration
É
État de chargement
État vide
Événement storage
F
FormData
Fuseau horaire
G
Géolocalisation
H
Horodatage Unix
HttpOnly
I
Idempotence
IndexedDB
Injection de script intersite
textContent pour les titres d’une API supprime l’interprétation HTML qui peut permettre une injection de script intersite.Intl.NumberFormat
Intl.NumberFormat pour chaque prix au lieu de reconstruire une chaîne monétaire pour chaque élément.J
Jeton d’accès
JSON
results avant de construire les éléments de liste.L
Limite de requêtes
localStorage
O
Objet Response
200, mais la page attend encore json() pour obtenir les données du livre.Opération synchrone
Origine
P
Pagination
Paramètre de requête
?, utilisée par un point de terminaison pour des entrées comme les recherches ou les limites de page.limit=12 demande au point de terminaison de recherche de renvoyer au plus douze résultats.Paramètres régionaux
en-US écrivent une date différemment de en-GB même lorsqu’ils mettent en forme le même instant.Partage de ressources entre origines (CORS)
Point de terminaison
POST pour créer une note et renvoie l’identifiant du nouvel enregistrement.Politique de même origine
Précision de la localisation
Promise.all
Promise.allSettled
Q
Quota de stockage
R
Région dynamique
role="status" annonce « Chargement… » puis le message de résultat de la recherche.Rendu
Réponse HTTP
404 et explique dans son corps que le livre demandé est introuvable.Réponse opaque
Requête HTTP
/books et comprend un paramètre de requête qui limite le nombre de résultats.Requête préliminaire
Retry-After
Retry-After de 15 demande à la page d’attendre quinze secondes avant une autre requête.S
Sérialisation
JSON.stringify préserve les champs d’une note lorsqu’ils sont envoyés dans un corps de requête JSON.sessionStorage
Solution de repli
T
Temps universel coordonné (UTC)
Z à la fin d’une date et heure ISO.textContent
textContent affiche ses chevrons littéralement au lieu de créer un élément HTML.U
Unité monétaire divisionnaire
4680 représente 46.80 dollars américains.W
Web Storage
À propos de cette unité
Crée ton propre Matériel d'Étude
Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.