| Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente |
| web:js:ajax [2023/03/31 03:24] – [Promise] jcheron | web:js:ajax [2023/10/12 11:11] (Version actuelle) – [API Fetch] jcheron |
|---|
| ===== Promise ===== | ===== Promise ===== |
| |
| Les promesses permettent d'écrire du code asynchrone, pour les méthodes qui nécessitent un temps de résolution. | Les promesses permettent d'écrire du code asynchrone, pour les méthodes qui nécessitent un temps d'exécution et ne peuvent retourner immédiatement un résultat. |
| |
| ==== Promise ==== | ==== Promise ==== |
| Exemple : Chargement d'un script : | === Exemple : Chargement d'un script === |
| <sxh javascript> | <sxh javascript> |
| function loadScript(src) { | function loadScript(src) { |
| }); | }); |
| } | } |
| | </sxh> |
| | * **resolve** permet d'indiquer que la promesse est résolue |
| | * **reject** qu'elle n'a pas abouti |
| | |
| | === Utilisation === |
| | |
| | <sxh javascript> |
| | let promise = loadScript("https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"); |
| | |
| | promise.then( |
| | script => alert(`${script.src} is loaded!`), |
| | error => alert(`Error: ${error.message}`) |
| | ); |
| </sxh> | </sxh> |
| |
| ==== async/await ==== | ==== async/await ==== |
| | |
| | L'utilisation de **async** et **await** permet d'utiliser les fonctions asynchrones sans obligation de chaîner les promesses (pas besoin de mettre le code dans le retour **then**). |
| | |
| | <sxh javascript;highlight:[9,11]> |
| | function resolveAfter2Seconds() { |
| | return new Promise(resolve => { |
| | setTimeout(() => { |
| | resolve('resolved'); |
| | }, 2000); |
| | }); |
| | } |
| | |
| | async function asyncCall() { |
| | console.log('calling'); |
| | const result = await resolveAfter2Seconds(); |
| | console.log(result); |
| | // Expected output: "resolved" |
| | } |
| | |
| | asyncCall(); |
| | </sxh> |
| |
| ===== API Fetch ===== | ===== API Fetch ===== |
| | |
| | L'api fetch permet en javascript d'effectuer des requêtes partielles vers le serveur, sans changer de page, selon le mode AJAX (Asynchronous Javascript And XML). |
| | |
| | **fetch** fonctionne selon la syntaxe suivante : |
| | <sxh javascript;gutter:false> |
| | let promise = fetch(url, [options]) |
| | </sxh> |
| | |
| | * Requête vers une **url** cible |
| | * en passant un tableau d'**option**s (méthode, headers...) |
| | |
| | Sans options, **fetch** effectue un simple **GET** téléchargeant le contenu. |
| | |
| | Lors de l'utilisation de **fetch**, la requête est envoyée vers le serveur et renvoie une promise qui pourra être utilisée via un objet **Response**. |
| | |
| | La réponse peut être analysée (via ses membres **status** ou **ok**, et on obtient son corps fourni sous la forme d'une seconde promesse : |
| | |
| | <sxh javascript> |
| | let response = await fetch(url); |
| | |
| | if (response.ok) { // Statut dans les 200 |
| | // obtenir le corps de réponse au format JSON |
| | let json = await response.json(); |
| | } else { |
| | alert("HTTP-Error: " + response.status); |
| | } |
| | </sxh> |
| | |
| | ==== Response ==== |
| | ^Méthode ^Action ^ |
| | ^response.headers() | Retourne les en-têtes de la réponse | |
| | ^response.text() | Retourne la réponse sous forme de texte | |
| | ^response.json() | Retourne la réponse au format JSON | |
| | ^response.formData() | Retourne un objet FormData | |
| | ^response.blob() | Retourne la réponse sous forme de blob (données binaires typées) | |
| | |
| | ==== Exemples ==== |
| | |
| | Requête vers l'api Github pour obtenir la liste des messages de commits d'un repo : |
| | |
| | Version **await** : |
| | <sxh javascript> |
| | let url = 'https://api.github.com/repos/cnam-dist/nfa085-2023/commits'; |
| | let response = await fetch(url); |
| | |
| | let commits = await response.json(); |
| | |
| | alert(commits[0].message); |
| | </sxh> |
| | |
| | Version **then** |
| | |
| | <sxh javascript> |
| | fetch('https://api.github.com/repos/cnam-dist/nfa085-2023/commits') |
| | .then(response => response.json()) |
| | .then(commits => alert(commits[0].message)); |
| | </sxh> |
| | |
| | |
| | Chargement d'image : |
| | |
| | <sxh javascript> |
| | let response = await fetch('/lib/tpl/bootstrap3/images/logo.png'); |
| | |
| | let blob = await response.blob(); // téléchargement en tant qu'objet Blob |
| | |
| | // Création d img |
| | let img = document.createElement('img'); |
| | img.style = 'position:fixed;top:10px;left:10px;width:100px'; |
| | document.body.append(img); |
| | |
| | // Affichage |
| | img.src = URL.createObjectURL(blob); |
| | |
| | setTimeout(() => { // Effacement après 3 secondes |
| | img.remove(); |
| | URL.revokeObjectURL(img.src); |
| | }, 3000); |
| | </sxh> |
| | |
| | <html> |
| | <div class="imageB"> |
| | <button id="ajax-load-image">Test image loading</button> |
| | </div> |
| | <script> |
| | document.getElementById("ajax-load-image").addEventListener("click", async function () { |
| | let response = await fetch('/lib/tpl/bootstrap3/images/logo.png'); |
| | |
| | let blob = await response.blob(); |
| | |
| | let img = document.createElement('img'); |
| | img.style = 'position:fixed;top:100px;left:100px;width:100px'; |
| | document.body.append(img); |
| | |
| | img.src = URL.createObjectURL(blob); |
| | |
| | setTimeout(() => { // le cacher après 3 secondes |
| | img.remove(); |
| | URL.revokeObjectURL(img.src); |
| | }, 3000); |
| | }); |
| | </script> |
| | </html> |
| | |
| | ==== Headers ==== |
| | === Response === |
| | L'objet **response** renvoyé contient un membre **headers** grace auquel il est possible dé récupérer les en-têtes : |
| | |
| | <sxh javascript> |
| | let response = await fetch('https://api.github.com/repos/cnam-dist/nfa085-2023/commits'); |
| | |
| | // récupération d'un header |
| | alert(response.headers.get('Content-Type')); // application/json; charset=utf-8 |
| | |
| | // itération sur tous les headers |
| | for (let [key, value] of response.headers) { |
| | alert(`${key} = ${value}`); |
| | } |
| | </sxh> |
| | === Request === |
| | Les headers de la requête sont envoyées au travers des options du fetch : |
| | <sxh javascript> |
| | let response = fetch(protectedUrl, { |
| | headers: { |
| | Authentication: 'secret' |
| | } |
| | }); |
| | </sxh> |
| | |
| | ==== POST ==== |
| | La méthode HTTP utilisée peut également être spécifiée au travers des options, comme les données envoyées dans le body : |
| | <sxh javascript> |
| | let user = { |
| | name: 'John', |
| | surname: 'DOE' |
| | }; |
| | |
| | let response = await fetch('/post/user', { |
| | method: 'POST', |
| | headers: { |
| | 'Content-Type': 'application/json;charset=utf-8' |
| | }, |
| | body: JSON.stringify(user) |
| | }); |
| | </sxh> |
| | |
| |
| |