aboutsummaryrefslogtreecommitdiff
path: root/files/fr/learn/javascript/client-side_web_apis/fetching_data/index.html
blob: 9fe8ea07d59192a99f027d0d7d95ba6f40690201 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
---
title: Récupérer des données du serveur
slug: Learn/JavaScript/Client-side_web_APIs/Fetching_data
tags:
  - API
  - Apprendre
  - Article
  - Codage
  - Débutant
  - Fetch
  - JavaScript
  - XHR
  - data
translation_of: Learn/JavaScript/Client-side_web_APIs/Fetching_data
original_slug: Apprendre/JavaScript/Client-side_web_APIs/Fetching_data
---
<div>{{LearnSidebar}}</div>

<div>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</div>

<p>Une autre tâche courante dans les sites et applications web modernes est de récupérer des données à partir du serveur pour mettre à jour des sections de la page web sans la recharger entièrement. Ce qui pourrait paraître comme un petit détail a, en vérité, eu un impact énorme sur les performances et le comportement des sites. Dans cet article, nous allons expliquer le concept et les technologies qui rendent cela possible, tels que XMLHttpRequest et l'API Fetch.</p>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="row">Prérequis :</th>
   <td>Notions de base de JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas</a>, <a href="/fr/Apprendre/JavaScript/Building_blocks">les briques JavaScript</a>, <a href="/fr/docs/Learn/JavaScript/Objects">les objets JavaScript</a>), les <a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction">notions de bases des APIs côté client</a></td>
  </tr>
  <tr>
   <th scope="row">Objectif :</th>
   <td>Apprendre à récupérer des données du serveur web et les utiliser pour mettre à jour le contenu de la page.</td>
  </tr>
 </tbody>
</table>

<h2 id="Quel_est_le_problème">Quel est le problème?</h2>

<p>À la base, le chargement d'une page web est simple — vous envoyez une requête à un serveur et, tant qu'il n'y a pas eu de problème, les ressources de la page web sont téléchargées et affichées sur votre ordinateur.</p>

<p><img alt="A basic representation of a web site architecture" src="web-site-architechture@2x.png"></p>

<p>Le problème avec ce modèle c'est qu'à chaque fois que vous voulez mettre à jour une partie de la page, par exemple pour afficher la page suivante d'une liste de produits, vous devez recharger toute la page. Ce surcoût est tout à fait inutile et résulte en une mauvaise expérience utilisateur, particulièrement pour les pages qui sont lourdes, complexes et du coup longues à charger.</p>

<h3 id="Larrivée_dAjax">L'arrivée d'Ajax</h3>

<p>Pour traiter ce problème, des technologies ont été élaborées qui permettent de récupérer à la demande de petites portions de données (comme du <a href="/fr/docs/Web/HTML">HTML</a>, {{glossary("XML")}}, <a href="/fr/docs/Learn/JavaScript/Objects/JSON">JSON</a>, ou texte brut) et de les afficher dans la page web.</p>

<p>Nous avons pour cela l'API {{domxref("XMLHttpRequest")}} à notre disposition ou — plus récemment — l'<a href="/fr/docs/Web/API/Fetch_API">API Fetch</a>. Elles permettent de réaliser des requêtes <a href="/fr/docs/Web/HTTP">HTTP</a> pour récupérer des ressources spécifiques disponibles sur un serveur et de formater les données retournées selon les besoins avant l'affichage dans la page.</p>

<div class="note">
<p><strong>Note :</strong> Dans les premiers temps, cette technique était appelée "Asynchronous JavaScript and XML" (JavaScript asychrone et XML), dit AJAX, parce qu'elle utilisait {{domxref("XMLHttpRequest")}} pour requêter des données XML. De nos jours, c'est rarement le cas; la plupart du temps, on utilise <code>XMLHttpRequest</code> ou Fetch pour requêter des données JSON. Quoi qu'il en soit, le procédé reste le même et le terme "Ajax" est resté pour décrire cette technique.</p>
</div>

<p><img alt="A simple modern architecture for web sites" src="moderne-web-site-architechture@2x.png"></p>

<p>Le modèle Ajax implique une API web comme proxy pour requêter les données plus intelligemment que simplement rafraîchir la page à chaque fois. Voyons plutôt l'impact que cela a :</p>

<ol>
 <li>Allez sur un site riche en information de votre choix, comme Amazon, YouTube, CNN...</li>
 <li>Cherchez quelque chose dans la barre de recherche, comme un nouveau produit. Le contenu principal va changer, mais la plupart de ce qui l'entoure reste statique, comme l'entête, le pied de page, le menu de navigation, etc.</li>
</ol>

<p>C'est une bonne chose puisque :</p>

<ul>
 <li>La mise à jour de la page est beaucoup plus rapide et vous n'avez pas à attendre que la page se rafraîchisse, si bien que le site paraît être plus rapide et plus réactif.</li>
 <li>Moins de données doivent être téléchargées pour mettre à jour la page, et donc moins de bande passante est utilisée. Cela ne fait peut-être pas une grande différence sur un ordinateur de bureau, mais cela peut devenir un problème majeur sur mobile ou dans les pays en développement, qui n'ont pas partout un service Internet ultra-rapide.</li>
</ul>

<p>Notez que pour accélerer les choses encore davantage, certains sites stockent les ressources et données chez le client lors de sa première visite, si bien que les visites suivantes, les fichiers locaux sont utilisés et non re-téléchargés du serveur. Le contenu n'est rechargé que lorsqu'il a été mis à jour sur le serveur.</p>

<p><img alt="A basic web app data flow architecture" src="web-app-architecture@2x.png"></p>

<h2 id="Une_requête_Ajax_basique">Une requête Ajax basique</h2>

<p>Voyons maintenant comment ces requêtes sont gérées, en utilisant soit {{domxref("XMLHttpRequest")}} soit <a href="/fr/docs/Web/API/Fetch_API">Fetch</a>. Pour ces exemples, nous allons requêter les données de différents fichiers texte et les utiliserons pour remplir une zone de contenu.</p>

<p>Ces fichiers agiront comme une fausse base de données ; dans une vraie application, il est plus probable que vous utiliseriez un langage côté serveur comme PHP, Python, ou Node pour récupérer les données à partir d'une véritable base de données. En revanche, nous voulons ici garder les choses simples ; nous allons donc nous concentrer sur le côté client.</p>

<h3 id="XMLHttpRequest">XMLHttpRequest</h3>

<p><code>XMLHttpRequest</code> (qui est fréquemment abrégé XHR) est une technologie assez vieille maintenant — elle a été inventée par Microsoft dans les années 90 et a été standardisée dans les autres navigateurs il y a longtemps.</p>

<ol>
 <li>
  <p>Pour commencer cet exemple, faites une copie locale de <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/ajax-start.html">ajax-start.html</a> et des quatre fichiers texte — <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse1.txt">verse1.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse2.txt">verse2.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse3.txt">verse3.txt</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse4.txt">verse4.txt</a> — dans un nouveau répertoire sur votre ordinateur. Dans cet exemple, nous allons charger le verset d'un poème (que vous pourriez bien reconnaître), quand il est sélectionné dans le menu déroulant, en utilisant XHR.</p>
 </li>
 <li>
  <p>À l'intérieur de l'élément {{htmlelement("script")}}, ajoutez le code qui suit. Il stocke une référence aux éléments {{htmlelement("select")}} et {{htmlelement("pre")}} dans des variables et définit un gestionnaire d'événement {{domxref("GlobalEventHandlers.onchange","onchange")}}, pour que, quand la valeur du menu déroulant est changée, la valeur sélectionnée soit passée comme paramètre à la fonction  <code>updateDisplay()</code>.</p>

  <pre class="brush: js">var verseChoose = document.querySelector('select');
var poemDisplay = document.querySelector('pre');

verseChoose.onchange = function() {
  var verse = verseChoose.value;
  updateDisplay(verse);
};</pre>
 </li>
 <li>
  <p>Définissons maintenant la fonction <code>updateDisplay()</code>. Tout d'abord, mettez ce qui suit au bas de votre JavaScript — c'est la structure vide de la fonction :</p>

  <pre class="brush: js">function updateDisplay(verse) {

};</pre>
 </li>
 <li>
  <p>Nous allons commencer notre fonction en construisant une URL relative qui pointe vers le fichier texte que nous voulons charger, nous en aurons besoin plus tard. La valeur de l'élément {{htmlelement("select")}} à tout instant est la même que l'élément {{htmlelement("option")}} sélectionné (c'est à dire le texte de l'élément sélectionné, ou son attribut <code>value</code> s'il est spécifié) — par exemple "Verse 1". Le fichier correspondant est "verse1.txt" et il est situé dans le même répertoire que le fichier HTML, le nom du fichier seul suffira donc.</p>

  <p>Les serveurs web sont généralement sensibles à la casse, le nom de fichier n'a pas d'espace et a une extension de fichier. Pour convertir "Verse 1" en "verse1.txt" nous allons convertir le "V" en minuscles avec {{jsxref("String.toLowerCase", "toLowerCase()")}}, supprimer l'espace avec {{jsxref("String.replace", "replace()")}} et ajouter ".txt" à la fin avec une simple <a href="/fr/docs/Learn/JavaScript/First_steps/Strings#Concaténation_de_chaînes">concaténation de chaînes</a>. Ajoutez les lignes suivantes à l'intérieur de la fonction <code>updateDisplay()</code> :</p>

  <pre class="brush: js">verse = verse.replace(" ", "");
verse = verse.toLowerCase();
var url = verse + '.txt';</pre>
 </li>
 <li>
  <p>Pour commencer à créer une requête XHR, vous allez devoir créer un nouvel objet avec le constructeur {{domxref("XMLHttpRequest.XMLHttpRequest", "XMLHttpRequest()")}}. Vous pouvez appeler cet objet comme vous le voulez, mais nous l'appellerons <code>request</code> pour plus de clarté. Ajoutez ce qui suit à vos lignes précédentes :</p>

  <pre class="brush: js">var request = new XMLHttpRequest();</pre>
 </li>
 <li>
  <p>Ensuite, vous allez devoir utiliser la méthode {{domxref("XMLHttpRequest.open","open()")}} pour spécifier la <a href="/fr/docs/Web/HTTP/Méthode">méthode HTTP</a> et l'URL à utiliser pour récupérer la ressource. Nous allons ici utiliser la méthode <code><a href="/fr/docs/Web/HTTP/Méthode/GET">GET</a></code> et passer notre variable <code>url</code> pour URL. Ajoutez ceci à la suite de la ligne précédente :</p>

  <pre class="brush: js">request.open('GET', url);</pre>
 </li>
 <li>
  <p>Nous allons définir le type de réponse que nous attendons — définit par la propriété {{domxref("XMLHttpRequest.responseType", "responseType")}} de la requête — comme <code>text</code>. Ce n'est pas strictement nécessaire ici — XHR retourne du texte par défaut — mais c'est une bonne idée d'en prendre l'habitude pour les cas où vous aurez besoin de définir un type différent. Ajoutez ceci à la suite :</p>

  <pre class="brush: js">request.responseType = 'text';</pre>
 </li>
 <li>
  <p>Récupérer une ressource sur le réseau est une opération {{glossary("asynchronous","asynchrone")}}, ce qui signifie que vous devez attendre que cette opération se termine (par exemple, que la ressource soit renvoyée) avant de pouvoir récupérer la réponse — sans quoi une erreur est levée. XHR permet d'exécuter du code lorsque la réponse est reçue grâce au gestionnaire d'événement {{domxref("XMLHttpRequest.onload", "onload")}} — quand l'événement {{event("load")}} est déclenché. Une fois que la réponse a été reçue, alors la réponse est accessible via la propriété <code>response</code> de l'objet XHR utilisé.</p>

  <p>Ajoutez le bloc de code qui suit toujours au bas de la fonction <code>updateDisplay()</code>. Vous verrez qu'à l'intérieur du gestionnaire d'événément <code>onload</code>, nous assignons la propriété <code><a href="/fr/docs/Web/API/Node/textContent">textContent</a></code> de <code>poemDisplay</code> (l'élément {{htmlelement("pre")}}) à la valeur de la propriété {{domxref("XMLHttpRequest.response", "request.response")}}.</p>

  <pre class="brush: js">request.onload = function() {
  poemDisplay.textContent = request.response;
};</pre>
 </li>
 <li>
  <p>Les étapes précédentes nous ont permis de configurer la requête XHR, mais celle-ci n'est exécutée que lorsqu'on le demande explicitement. Pour ce faire, il faut appeler la méthode {{domxref("XMLHttpRequest.send","send()")}}. Ajoutez la ligne suivante à la suite du code déjà écrit :</p>

  <pre class="brush: js">request.send();</pre>

  <p>Voyez la section {{anch("Serving your example from a server", "Servir votre exemple depuis un serveur")}} pour pouvoir tester.</p>
 </li>
 <li>
  <p>Un dernier problème avec cet exemple est qu'il ne montre rien au chargement de la page (mais uniquement à la sélection d'un verset). Pour corriger cela, ajoutez ce qui suit au bas de votre code (juste au-dessus de la balise fermante <code>&lt;/script&gt;</code>), pour charger le verset 1 par défaut, et s'assurer que l'élément {{htmlelement("select")}} montre toujours la bonne valeur :</p>

  <pre class="brush: js">updateDisplay('Verse 1');
verseChoose.value = 'Verse 1';</pre>
 </li>
</ol>

<h3 id="Servir_votre_exemple_depuis_un_serveur">Servir votre exemple depuis un serveur</h3>

<p>Certains navigateurs (dont Chrome) n'exécuteront pas de requêtes XHR si vous exécutez votre script simplement à partir d'un fichier local. Cela est dû à des restrictions de sécurité (pour plus d'infos sur la sécurité web, consultez l'article <a href="/fr/docs/Learn/Server-side/First_steps/Website_security">La sécurité d'un site web</a>).</p>

<p>Pour règler ce problème, vous devez tester l'exemple à travers un serveur web local. Pour savoir comment procéder, lisez <a href="/fr/Apprendre/Common_questions/configurer_un_serveur_de_test_local">Comment configurer un serveur de test local?</a></p>

<h3 id="Fetch">Fetch</h3>

<p>L'API Fetch est une solution moderne qui vient remplacer XHR — elle a été introduite récemment dans les navigateurs pour rendre les requêtes HTTP asynchrones plus simples en JavaScript, à la fois pour les développeurs et pour les autres APIs qui utilisent cette technologie.</p>

<p>Voyons comment convertir le dernier exemple, en remplaçant XHR par Fetch.</p>

<ol>
 <li>
  <p>Faites une copie du répertoire de votre dernier exemple. (Ou si vous ne l'avez pas fait, créez un nouveau répertoire et copiez le fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/xhr-basic.html">xhr-basic.html</a> et les quatre fichiers texte — <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse1.txt">verse1.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse2.txt">verse2.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse3.txt">verse3.txt</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse4.txt">verse4.txt</a> — à l'intérieur).</p>
 </li>
 <li>
  <p>À l'intérieur de la fonction <code>updateDisplay()</code>, vous avez le code XHR suivant :</p>

  <pre class="brush: js">var request = new XMLHttpRequest();
request.open('GET', url);
request.responseType = 'text';

request.onload = function() {
  poemDisplay.textContent = request.response;
};

request.send();</pre>
 </li>
 <li>
  <p>Remplacez-le avec ce qui suit :</p>

  <pre class="brush: js">fetch(url).then(function(response) {
  response.text().then(function(text) {
    poemDisplay.textContent = text;
  });
});</pre>
 </li>
 <li>
  <p>Chargez l'exemple dans votre navigateur (en l'exécutant à travers un serveur web) et il devrait produire le même résultat que la version XHR  — pourvu que vous utilisiez un navigateur moderne.</p>
 </li>
</ol>

<h4 id="Que_se_passe-t-il_dans_le_code_Fetch">Que se passe-t-il dans le code Fetch?</h4>

<p>Tout d'abord, nous invoquons la méthode {{domxref("WindowOrWorkerGlobalScope.fetch()","fetch()")}}, en lui passant l'URL de la ressource que nous voulons récupérer. C'est la version moderne équivalente à {{domxref("XMLHttpRequest.open","request.open()")}} de XHR, et n'avez pas à appeler <code>.send()</code> — la requête est exécutée directemment.</p>

<p>Ensuite, la méthode {{jsxref("Promise.then",".then()")}} est chaînée à la suite de <code>fetch()</code> — cette méthode fait partie des {{jsxref("Promise","Promesses")}}, une fonctionnalité JavaScript moderne qui permet d'effectuer des opérations asynchrones. <code>fetch()</code> retourne une promesse, qui est résolue lorsque la réponse est reçue du serveur — et nous utilisons <code>.then()</code> pour exécuter du code à ce moment là. C'est l'équivalent du gestionnaire d'événément <code>onload</code> dans la version XHR.</p>

<p>La fonction définie dans le <code>.then()</code> reçoit la réponse du serveur comme paramètre, une fois que la promesse retournée par <code>fetch()</code> est résolue. À l'intérieur de cette fonction, nous utilisons la méthode {{domxref("Body.text","text()")}} pour récupérer le contenu de la réponse en texte brut. C'est l'équivalent de <code>request.responseType = 'text'</code> dans la version XHR.</p>

<p>Vous verrez que <code>text()</code> retourne également une promesse, nous y chaînons donc un nouveau <code>.then()</code>, à l'intérieur de quoi nous définissons une fonction. Cette dernière récupère quant à elle le texte brut que la promesse précédente résout.</p>

<p>Enfin, dans le corps de la fonction, nous faisons la même chose que nous faisions dans la version XHR — définir le contenu texte de l'élément {{htmlelement("pre")}} au texte récupéré.</p>

<h3 id="À_propos_des_promesses">À propos des promesses</h3>

<p>Les promesses peuvent être un peu déroutantes au premier abord, ne vous en souciez pas trop pour l'instant. Vous vous y ferez après un certain temps, d'autant plus après en avoir appris davantage sur les APIs JavaScript modernes — la plupart des APIs récentes utilisent beaucoup les promesses.</p>

<p>Regardons à nouveau la structure d'une promesse pour voir si nous pouvons en donner plus de sens.</p>

<h4 id="Promesse_1">Promesse 1</h4>

<pre class="brush: js">fetch(url).then(function(response) {
  //...
});</pre>

<p>Si l'on traduit en bon français les instructions JavaScript, on pourrait dire</p>

<ul>
 <li><code>fetch(url)</code> : récupérer la ressource située à l'adresse <code>url</code></li>
 <li><code>.then(function() { ... })</code>: quand c'est fait, exécuter la fonction spécifiée</li>
</ul>

<p>On dit qu'une promesse est "résolue" (resolved) lorsque l'opération spécifiée à un moment donné est terminée. En l'occurence, l'opération spécifiée est de récupérer une ressource à une URL donnée (en utilisant une requête HTTP) et de retourner la réponse reçue du serveur.</p>

<p>La fonction passée à <code>then()</code> n'est pas exécutée immédiatement — elle est exécutée à un moment dans le futur, dès que la promesse est résolue (c'est à dire qu'elle a retourné la réponse du serveur).</p>

<p>Notez que vous pouvez également choisir de stocker votre promesse dans une variable, et de chaîner le {{jsxref("Promise.then",".then()")}} sur cette variable. L'exemple suivant fait la même chose que le précédent :</p>

<pre class="brush: js">var myFetch = fetch(url);

myFetch.then(function(response) {
  //...
});</pre>

<p>Parce que la méthode <code>fetch()</code> retourne une promesse qui résout une réponse HTTP, la fonction définie à l'intérieur du <code>.then()</code> reçoit la réponse en tant que paramètre. Vous pouvez appeler le paramètre comme vous souhaitez — l'exemple ci-dessous fait toujours la même chose :</p>

<pre class="brush: js">fetch(url).then(function(dogBiscuits) {
  //...
});</pre>

<p>Mais il est plus logique de donner un nom de paramètre qui décrit son contenu !</p>

<h4 id="Promesse_2">Promesse 2</h4>

<p>Voyons maintenant la fonction appelé dans <code>.then()</code>:</p>

<pre class="brush: js">function(response) {
  response.text().then(function(text) {
    poemDisplay.textContent = text;
  });
}</pre>

<p>L'objet <code>response</code> a une méthode {{domxref("Body.text","text()")}}, qui convertit les données brutes contenues dans la réponse en texte brut — c'est le format que nous voulons. Cette méthode retourne également une promesse, qui se résout lorsque la réponse est convertie en texte, nous utilisons donc un deuxième {{jsxref("Promise.then",".then()")}} pour cette deuxième promesse.</p>

<p>À l'intérieur de ce dernier <code>.then()</code>, nous définissons une nouvelle fonction, qui décide de ce que nous faisons avec le texte récupéré. Nous nous contentons de définir la propriété <code><a href="/fr/docs/Web/API/Node/textContent">textContent</a></code> de l'élément {{htmlelement("pre")}} à la valeur du texte.</p>

<h4 id="Chaîner_les_then">Chaîner les then()</h4>

<p>Notez que le résultat de la fonction appelée par le <code>.then()</code> est également retourné par ce dernier, nous pouvons donc mettre les <code>.then()</code> bout à bout, en passant le résultat du bloc précédent au prochain.</p>

<p>Ainsi, le bloc de code suivant fait la même chose que notre exemple original, mais écrit dans un style différent :</p>

<pre class="brush: js">fetch(url).then(function(response) {
  return response.text()
}).then(function(text) {
  poemDisplay.textContent = text;
});</pre>

<p>Beaucoup de développeurs préfèrent ce style, plus "plat" : il évite de définir des fonctions à l'intérieur de fonctions et est plus facile à lire lorsqu'il y a beaucoup de promesses qui s'enchaînent. La seule différence ici est que nous avons une instruction <code><a href="/fr/Apprendre/JavaScript/Building_blocks/Return_values">return</a></code> pour retourner <code>response.text()</code>, et ce résultat est passé au prochain <code>.then()</code>.</p>

<h3 id="Quel_mécanisme_devriez-vous_utiliser">Quel mécanisme devriez-vous utiliser?</h3>

<p>Cela dépend du projet sur lequel vous travaillez. XHR existe depuis longtemps maintenant et bénéficie d'un très bon support sur les différents navigateurs. Fetch et les promesses, en revanche, sont un ajout plus récent à la plateforme web, bien qu'ils soient pris en charge par la plupart des navigateurs, Internet Explorer et Safari font exception.</p>

<p>Si vous voulez un support des anciens navigateurs, alors XHR est probablement la solution préférable. En revanche, si vous travaillez sur un projet plus progressif, et que vous n'êtes pas tant préoccupé par les anciens navigateurs, alors Fetch peut être un bon choix.</p>

<p>Vous devriez apprendre les deux alternatives — Fetch deviendra plus populaire au fur et à mesure que l'utilisation d'Internet Explorer diminue (IE n'est plus développé, en faveur du nouveau navigateur de Microsoft, Edge), mais vous allez avoir besoin de XHR pendant un moment encore.</p>

<h2 id="Un_exemple_plus_complexe">Un exemple plus complexe</h2>

<p>Pour clore l'article, nous allons regarder un exemple un peu plus complexe, qui montre des utilisations plus intéressantes de Fetch. Nous avons créé un site d'exemple appelé The Can Store (le magasin de conserves) — c'est un supermarché fictif qui ne vend que des boites de conserves. Vous pouvez trouver cet <a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/">exemple en direct sur GitHub</a>, et <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/fetching-data/can-store">voir le code source</a>.</p>

<p><img alt="A fake ecommerce site showing search options in the left hand column, and product search results in the right hand column." src="can-store.png"></p>

<p>Par défaut, le site affiche tous les produits ; mais vous pouvez utiliser le formulaire dans la colonne de gauche pour les filtrer par catégorie, ou chercher un terme, ou les deux.</p>

<p>Il y a du code plutôt complexe pour traiter le filtrage des produits par catégorie et par terme de recherche, manipulant les chaînes de caractères pour afficher les données correctement dans l'interface utilisateur, etc. Nous n'allons pas en discuter dans cet article, mais vous pouvez trouver des commentaires très complets dans le code (voir <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-script.js">can-script.js</a>). Nous allons expliquer le code Fetch.</p>

<h4 id="Premier_Fetch">Premier Fetch</h4>

<p>Le premier bloc qui utilise Fetch se trouve au début du JavaScript :</p>

<pre class="brush: js">fetch('products.json').then(function(response) {
  if(response.ok) {
    response.json().then(function(json) {
      products = json;
      initialize();
    });
  } else {
    console.log('Network request for products.json failed with response ' + response.status + ': ' + response.statusText);
  }
});</pre>

<p>Cela ressemble à ce que vous avons vu précédemment, sauf que la deuxième promesse est à l'intérieur d'une condition. Cette condition vérifie si la réponse retournée est un succès ou non — la propriété {{domxref("response.ok")}} contient un booléen qui vaut <code>true</code> si le statut de la réponse était OK (<a href="/fr/docs/Web/HTTP/Status/200">statut HTTP 200, "OK"</a>), ou <code>false</code> sinon.</p>

<p>Si la réponse était un succès, nous déclenchons la deuxième promesse — cette fois-ci en utilisant {{domxref("Body.json","json()")}} et non {{domxref("Body.text","text()")}}, puisque nous voulons récupérer la réponse sous forme de données structurées JSON et non de texte brut.</p>

<p>Si la réponse n'est pas un succès, nous affichons une erreur dans la console indiquant que la requête réseau a échoué, avec le statut et le message obtenus (contenus dans les propriétés {{domxref("response.status")}} et {{domxref("response.statusText")}} respectivement). Bien sûr, un véritable site web traiterait cette erreur plus gracieusement, en affichant un message à l'écran en offrant peut-être des options pour remédier à la situation.</p>

<p>Vous pouvez tester le cas d'échec vous-même :</p>

<ol>
 <li>Faites une copie locale des fichiers d'exemple (téléchargez et dézippez le <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-store.zip?raw=true">fichier ZIP can-store</a>)</li>
 <li>Éxecutez le code via un serveur web (comme vu précédemment dans {{anch("Serving your example from a server", "Servir votre exemple depuis un serveur")}})</li>
 <li>Modifiez le chemin du fichier à récupérer, mettez un nom de fichier qui n'existe pas, comme 'produc.json'.</li>
 <li>Maintenant, chargez le fichier index dans votre navigateur (via <code>localhost:8000</code>) et regardez dans la console de développement. Vous verrez un message parmi les lignes "Network request for products.json failed with response 404: File not found" (la requête réseau pour products.json a échoué avec la réponse 404: Fichier non trouvé).</li>
</ol>

<h4 id="Deuxième_Fetch">Deuxième Fetch</h4>

<p>Le deuxième bloc Fetch se trouve dans la fonction <code>fetchBlob()</code>:</p>

<pre class="brush: js">fetch(url).then(function(response) {
  if(response.ok) {
    response.blob().then(function(blob) {
      objectURL = URL.createObjectURL(blob);
      showProduct(objectURL, product);
    });
  } else {
    console.log('Network request for "' + product.name + '" image failed with response ' + response.status + ': ' + response.statusText);
  }
});</pre>

<p>Cela fonctionne à peu près de la même manière que le précédent, sauf qu'au lieu d'utiliser {{domxref("Body.json","json()")}}, on utilise {{domxref("Body.blob","blob()")}} — en l'occurence, nous voulons récupérer la réponse sous la forme d'un fichier image, et le format de données que nous utilisons est <a href="/fr/docs/Web/API/Blob">Blob</a> — ce terme est une abbréviation de "Binary Large Object" (large objet binaire) et peut être utilisé pour représenter de gros objets fichier — tels que des fichiers images ou vidéo.</p>

<p>Une fois que nous avons reçu notre blob avec succès, nous créons un objet URL, en utilisant {{domxref("URL.createObjectURL()", "createObjectURL()")}}. Cela renvoie une URL interne temporaire qui pointe vers un blob en mémoire dans le navigateur. Cet objet n'est pas très lisible, mais vous pouvez voir à quoi il ressemble en ouvrant l'application Can Store, Ctrl + Clic droit sur l'image, et sélectionner l'option "Afficher l'image" (peut légèrement varier selon le navigateur que vous utilisez). L'URL créée sera visible à l'intérieur de la barre d'adresse et devrait ressembler à quelque chose comme ça :</p>

<pre>blob:http://localhost:7800/9b75250e-5279-e249-884f-d03eb1fd84f4</pre>

<h3 id="Challenge_une_version_XHR_de_Can_Store">Challenge : une version XHR de Can Store</h3>

<p>Comme exercice pratique, nous aimerions que vous essayiez de convertir la version Fetch de l'application en une version XHR. Faites une <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-store.zip?raw=true">copie du fichier ZIP</a> et essayiez de modifier le JavaScript en conséquence.</p>

<p>Quelques conseils qui pourraient s'avérer utiles :</p>

<ul>
 <li>Vous pourriez trouver la référence {{domxref("XMLHttpRequest")}} utile.</li>
 <li>Vous allez devoir utiliser le même modèle que vous avez vu plus tôt dans l'exemple <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/xhr-basic.html">XHR-basic.html</a>.</li>
 <li>Vous devrez ajouter la gestion des erreurs que nous vous avons montré dans la version Fetch de Can Store :
  <ul>
   <li>La réponse se situe dans <code>request.response</code> une fois que l'événement <code>load</code> a été déclenché et non dans une promesse.</li>
   <li>Le meilleur équivalent à <code>response.ok</code> en XHR est de vérifier si {{domxref("XMLHttpRequest.status","request.status")}} vaut 200 ou si {{domxref("XMLHttpRequest.readyState","request.readyState")}} est égal à 4.</li>
   <li>Les propriétés permettant d'obtenir le status et le message en cas d'erreur sont toujours <code>status</code> et <code>statusText</code> mais elles se situent sur l'objet <code>request</code> (XHR) et non sur l'objet <code>response</code>.</li>
  </ul>
 </li>
</ul>

<div class="note">
<p><strong>Note :</strong> Si vous avez des difficultés à le faire, vous pouvez comparer votre code à la version finale sur GitHub (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store-xhr/can-script.js">voir le code source</a>, ou <a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store-xhr/">voir en direct</a>).</p>
</div>

<h2 id="Sommaire">Sommaire</h2>

<p>Voilà qui clôt notre article sur la récupération de données à partir du serveur. À ce stade, vous devriez savoir comment travailler avec XHR et Fetch.</p>

<h2 id="Voir_aussi">Voir aussi</h2>

<p>Il y a beaucoup de sujets abordés dans cet article, dont nous n'avons qu'égratigné la surface. Pour plus de détails sur ces sujets, essayez les articles suivants:</p>

<ul>
 <li><a href="/fr/docs/Web/Guide/AJAX/Premiers_pas">Ajax — Premiers pas</a></li>
 <li><a href="/fr/docs/Web/API/Fetch_API/Using_Fetch">Utiliser Fetch</a></li>
 <li><a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise">Promesses</a></li>
 <li><a href="/fr/docs/Learn/JavaScript/Objects/JSON">Manipuler des données JSON</a></li>
 <li><a href="/fr/docs/Web/HTTP/Aperçu">Un aperçu de HTTP</a></li>
 <li><a href="/fr/docs/Learn/Server-side">Programmation de sites web, côté serveur</a></li>
</ul>

<div>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</div>

<div>
<h2 id="Dans_ce_module">Dans ce module</h2>

<ul>
 <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction">Introduction aux API du Web</a></li>
 <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipuler des documents</a></li>
 <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data">Récupérer des données du serveur</a></li>
 <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs">APIs tierces</a></li>
 <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des éléments graphiques</a></li>
 <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">APIs vidéo et audio</a></li>
 <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage">Stockage côté client</a></li>
</ul>
</div>