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
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
|
---
title: Faciliter la programmation asynchrone avec async et await
slug: Learn/JavaScript/Asynchronous/Async_await
tags:
- Beginner
- CodingScripting
- Guide
- JavaScript
- Learn
- Promises
- async
- asynchronous
- await
translation_of: Learn/JavaScript/Asynchronous/Async_await
---
<div>{{LearnSidebar}}</div>
<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Choosing_the_right_approach", "Learn/JavaScript/Asynchronous")}}</div>
<p>Plus récemment, les <a href="/fr/docs/Web/JavaScript/Reference/Statements/async_function">fonctions async</a> et le mot-clé <code><a href="/fr/docs/Web/JavaScript/Reference/Operators/await">await</a></code> ont été ajoutés au langage JavaScript avec l'édition intitulée ECMAScript 2017. Ces fonctionnalités agissent essentiellement comme du sucre syntaxique sur les promesses, rendant le code asynchrone plus facile à écrire et à lire par la suite. Elles font en sorte que le code asynchrone ressemble davantage au code synchrone de la vieille école, et elles valent donc la peine d'être apprises. Cet article fournit les informations à connaître.</p>
<table class="standard-table">
<tbody>
<tr>
<th scope="row">Prérequis :</th>
<td>Connaissances informatiques de base, compréhension raisonnable des principes fondamentaux de JavaScript, compréhension du code asynchrone en général et des promesses.</td>
</tr>
<tr>
<th scope="row">Objectif :</th>
<td>Comprendre <code>async/await</code> et comment les utiliser.</td>
</tr>
</tbody>
</table>
<h2 id="the_basics_of_asyncawait">Les bases de async/await</h2>
<p>L'utilisation <code>async/await</code> dans votre code comporte deux parties.</p>
<h3 id="the_async_keyword">Le mot-clé async</h3>
<p>Tout d'abord, nous avons le mot-clé <code>async</code>, que vous mettez devant une déclaration de fonction pour la transformer en une <a href="/fr/docs/Web/JavaScript/Reference/Statements/async_function">fonction asynchrone</a>. Une fonction asynchrone est une fonction qui saura réagir à une éventuelle utilisation du mot-clé <code>await</code> pour invoquer du code asynchrone.</p>
<p>Essayez de taper les lignes suivantes dans la console JS de votre navigateur :</p>
<pre class="brush: js">function hello() { return "Bonjour" };
hello();</pre>
<p>La fonction renvoie « Bonjour » — rien de spécial, n'est-ce pas ?</p>
<p>Mais que se passe-t-il si nous transformons cette fonction en une fonction asynchrone ? Essayez ce qui suit :</p>
<pre class="brush: js">async function hello() { return "Bonjour" };
hello();</pre>
<p>Ah. L'invocation de la fonction renvoie maintenant une promesse. C'est l'une des caractéristiques des fonctions asynchrones - leurs valeurs de retour sont nécessairement converties en promesses.</p>
<p>Vous pouvez également créer une <a href="/fr/docs/Web/JavaScript/Reference/Operators/async_function">expression de fonction asynchrone</a>, comme suit :</p>
<pre class="brush: js">let hello = async function() { return "Bonjour" };
hello();</pre>
<p>Et vous pouvez utiliser les fonctions fléchées :</p>
<pre class="brush: js">let hello = async () => { return "Bonjour" };</pre>
<p>Elles font toutes à peu près la même chose.</p>
<p>Pour consommer réellement la valeur renvoyée lorsque la promesse se réalise, puisqu'elle renvoie une promesse, nous pourrions utiliser un bloc <code>.then()</code> :</p>
<pre class="brush: js">hello().then((value) => console.log(value));</pre>
<p>ou même simplement un raccourci tel que</p>
<pre class="brush: js">hello().then(console.log);</pre>
<p>Comme nous l'avons vu dans l'article précédent.</p>
<p>Ainsi, le mot-clé <code>async</code> est ajouté aux fonctions pour leur indiquer de retourner une promesse plutôt que de retourner directement la valeur.</p>
<h3 id="the_await_keyword">Le mot-clé await</h3>
<p>L'avantage d'une fonction asynchrone ne devient apparent que lorsque vous la combinez avec le mot-clé <code>await</code>. <code>await</code> ne fonctionne qu'à l'intérieur de fonctions asynchrones dans du code JavaScript ordinaire, mais il peut être utilisé seul avec <a href="/fr/docs/Web/JavaScript/Guide/Modules">des modules JavaScript</a>.</p>
<p><code>await</code> peut être placé devant toute fonction asynchrone basée sur une promesse pour mettre en pause votre code sur cette ligne jusqu'à ce que la promesse se réalise, puis retourner la valeur résultante.</p>
<p>Vous pouvez utiliser <code>await</code> lors de l'appel de toute fonction qui renvoie une promesse, y compris les fonctions de l'API web.</p>
<p>Voici un exemple trivial :</p>
<pre class="brush: js">async function hello() {
return salutation = await Promise.resolve("Bonjour");
};
hello().then(console.log);</pre>
<p>Bien sûr, l'exemple ci-dessus n'est pas très utile, même s'il sert à illustrer la syntaxe. Passons maintenant à un exemple réel.</p>
<h2 id="rewriting_promise_code_with_asyncawait">Réécriture du code des promesses avec async/await</h2>
<p>Reprenons un exemple simple de récupération que nous avons vu dans l'article précédent :</p>
<pre class="brush: js">fetch('coffee.jpg')
.then(response => {
if (!response.ok) {
throw new Error(`Erreur HTTP ! statut : ${response.status}`);
}
return response.blob();
})
.then(myBlob => {
let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
})
.catch(e => {
console.log('Il y a eu un problème avec votre opération de récupération : ' + e.message);
});</pre>
<p>À ce stade, vous devriez avoir une compréhension raisonnable des promesses et de leur fonctionnement, mais convertissons le tout en utilisant async/await pour voir à quel point cela simplifie les choses :</p>
<pre class="brush: js">async function myFetch() {
let response = await fetch('coffee.jpg');
if (!response.ok) {
throw new Error(`Erreur HTTP ! statut : ${response.status}`);
}
let myBlob = await response.blob();
let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
}
myFetch()
.catch(e => {
console.log('Il y a eu un problème avec votre opération de récupération : ' + e.message);
});</pre>
<p>Cela rend le code beaucoup plus simple et plus facile à comprendre — plus de blocs <code>.then()</code> partout !</p>
<p>Étant donné qu'un mot-clé <code>async</code> transforme une fonction en promesse, vous pourriez remanier votre code pour utiliser une approche hybride de promesses et de <code>await</code>, en faisant sortir la seconde moitié de la fonction dans un nouveau bloc pour la rendre plus flexible :</p>
<pre class="brush: js">async function myFetch() {
let response = await fetch('coffee.jpg');
if (!response.ok) {
throw new Error(`Erreur HTTP ! statut : ${response.status}`);
}
return await response.blob();
}
myFetch().then((blob) => {
let objectURL = URL.createObjectURL(blob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
}).catch(e => console.log(e));</pre>
<p>Vous pouvez essayer de taper vous-même l'exemple, ou d'exécuter notre <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await.html">exemple en direct</a> (voir aussi le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await.html">code source</a>).</p>
<h3 id="but_how_does_it_work">Mais comment est-ce que cela fonctionne ?</h3>
<p>Vous remarquerez que nous avons enveloppé le code à l'intérieur d'une fonction, et que nous avons inclus le mot-clé <code>async</code> avant le mot-clé <code>function</code>. C'est nécessaire - vous devez créer une fonction async pour définir un bloc de code dans lequel vous exécuterez votre code async ; comme nous l'avons dit précédemment, <code>await</code> ne fonctionne qu'à l'intérieur de fonctions async.</p>
<p>À l'intérieur de la définition de la fonction <code>myFetch()</code>, vous pouvez voir que le code ressemble beaucoup à la version précédente de la promesse, mais il y a quelques différences. Au lieu de devoir enchaîner un bloc <code>.then()</code> à la fin de chaque méthode basée sur une promesse, il suffit d'ajouter un mot-clé <code>await</code> avant l'appel de la méthode, puis d'affecter le résultat à une variable. Le mot-clé <code>await</code> fait en sorte que le moteur d'exécution JavaScript mette votre code en pause sur cette ligne, ne permettant pas à d'autres codes de s'exécuter entre-temps jusqu'à ce que l'appel de fonction asynchrone ait retourné son résultat - très utile si le code suivant dépend de ce résultat !</p>
<p>Une fois que c'est terminé, votre code continue à s'exécuter à partir de la ligne suivante. Par exemple :</p>
<pre class="brush: js">let response = await fetch('coffee.jpg');</pre>
<p>La réponse retournée par la promesse <code>fetch()</code> remplie est affectée à la variable <code>response</code> lorsque cette réponse devient disponible, et le parseur fait une pause sur cette ligne jusqu'à ce que cela se produise. Une fois que la réponse est disponible, le parseur passe à la ligne suivante, qui crée un <code><a href="/fr/docs/Web/API/Blob">Blob</a></code> à partir de celle-ci. Cette ligne invoque également une méthode async basée sur les promesses, nous utilisons donc <code>await</code> ici aussi. Lorsque le résultat de l'opération revient, nous le retournons hors de la fonction <code>myFetch()</code>.</p>
<p>Cela signifie que lorsque nous appelons la fonction <code>myFetch()</code>, elle retourne une promesse, de sorte que nous pouvons enchaîner un <code>.then()</code> à la fin de celle-ci à l'intérieur duquel nous gérons l'affichage du blob à l'écran.</p>
<p>Vous vous dites probablement déjà « c'est vraiment cool ! », et vous avez raison — moins de blocs <code>.then()</code> pour envelopper le code, et cela ressemble surtout à du code synchrone, donc c'est vraiment intuitif.</p>
<h3 id="adding_error_handling">Ajout de la gestion des erreurs</h3>
<p>Si vous voulez ajouter la gestion des erreurs, vous avez plusieurs options.</p>
<p>Vous pouvez utiliser une structure synchrone <code><a href="/fr/docs/Web/JavaScript/Reference/Statements/try...catch">try...catch</a></code> avec <code>async</code>/<code>await</code>. Cet exemple développe la première version du code que nous avons montré ci-dessus :</p>
<pre class="brush: js">async function myFetch() {
try {
let response = await fetch('coffee.jpg');
if (!response.ok) {
throw new Error(`Erreur HTTP ! statut : ${response.status}`);
}
let myBlob = await response.blob();
let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
} catch(e) {
console.log(e);
}
}
myFetch();</pre>
<p>Le bloc <code>catch() {}</code> reçoit un objet d'erreur, que nous avons appelé <code>e</code> ; nous pouvons maintenant l'enregistrer dans la console, et il nous donnera un message d'erreur détaillé montrant où dans le code l'erreur a été lancée.</p>
<p>Si vous vouliez utiliser la deuxième version (remaniée) du code que nous avons montré ci-dessus, il serait préférable de continuer l'approche hybride et d'enchaîner un bloc <code>.catch()</code> à la fin de l'appel <code>.then()</code>, comme ceci :</p>
<pre class="brush: js">async function myFetch() {
let response = await fetch('coffee.jpg');
if (!response.ok) {
throw new Error(`Erreur HTTP ! statut : ${response.status}`);
}
return await response.blob();
}
myFetch().then((blob) => {
let objectURL = URL.createObjectURL(blob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
})
.catch((e) =>
console.log(e)
);</pre>
<p>En effet, le bloc <code>.catch()</code> attrapera les erreurs survenant à la fois dans l'appel de fonction asynchrone et dans la chaîne de promesses. Si vous utilisiez le bloc <code>try</code>/<code>catch</code> ici, vous pourriez toujours obtenir des erreurs non gérées dans la fonction <code>myFetch()</code> lorsqu'elle est appelée.</p>
<p>Vous pouvez trouver ces deux exemples sur GitHub :</p>
<ul>
<li><a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await-try-catch.html">simple-fetch-async-await-try-catch.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await-try-catch.html">code source</a>)</li>
<li><a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await-promise-catch.html">simple-fetch-async-await-promise-catch.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await-promise-catch.html">code source</a>)</li>
</ul>
<h2 id="awaiting_a_promise.all">En attente d'un Promise.all()</h2>
<p><code>async</code>/<code>await</code> est construit au-dessus de <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise" >Promises</a>, il est donc compatible avec toutes les fonctionnalités offertes par les promesses. Cela inclut <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise.all()</a></code> — vous pouvez tout à fait attendre un appel <code>Promise.all()</code> pour obtenir tous les résultats retournés dans une variable d'une manière qui ressemble à du simple code synchrone. Encore une fois, revenons à <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html">un exemple que nous avons vu dans notre article précédent</a>. Gardez-le ouvert dans un onglet séparé afin de pouvoir le comparer avec la nouvelle version présentée ci-dessous.</p>
<p>En convertissant cela en <code>async</code>/<code>await</code> (voir la <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/promise-all-async-await.html">démo live</a> et le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/promise-all-async-await.html">code source</a>), cela ressemble maintenant à ceci :</p>
<pre class="brush: js">async function fetchAndDecode(url, type) {
let response = await fetch(url);
let content;
if (!response.ok) {
throw new Error(`Erreur HTTP ! statut : ${response.status}`);
} else {
if(type === 'blob') {
content = await response.blob();
} else if(type === 'text') {
content = await response.text();
}
}
return content;
}
async function displayContent() {
let coffee = fetchAndDecode('coffee.jpg', 'blob');
let tea = fetchAndDecode('tea.jpg', 'blob');
let description = fetchAndDecode('description.txt', 'text');
let values = await Promise.all([coffee, tea, description]);
let objectURL1 = URL.createObjectURL(values[0]);
let objectURL2 = URL.createObjectURL(values[1]);
let descText = values[2];
let image1 = document.createElement('img');
let image2 = document.createElement('img');
image1.src = objectURL1;
image2.src = objectURL2;
document.body.appendChild(image1);
document.body.appendChild(image2);
let para = document.createElement('p');
para.textContent = descText;
document.body.appendChild(para);
}
displayContent()
.catch((e) =>
console.log(e)
);</pre>
<p>Vous verrez que la fonction <code>fetchAndDecode()</code> a été convertie facilement en fonction asynchrone avec seulement quelques modifications. Voir la ligne <code>Promise.all()</code> :</p>
<pre class="brush: js">let values = await Promise.all([coffee, tea, description]);</pre>
<p>En utilisant <code>await</code> ici, nous sommes en mesure d'obtenir tous les résultats des trois promesses retournées dans le tableau <code>values</code>, quand ils sont tous disponibles, d'une manière qui ressemble beaucoup à du code synchrone. Nous avons dû envelopper tout le code dans une nouvelle fonction asynchrone, <code>displayContent()</code>, et nous n'avons pas réduit le code de beaucoup de lignes, mais être capable de déplacer la majeure partie du code hors du bloc <code>.then()</code> fournit une simplification agréable et utile, nous laissant avec un programme beaucoup plus lisible.</p>
<p>Pour la gestion des erreurs, nous avons inclus un bloc <code>.catch()</code> sur notre appel <code>displayContent()</code> ; cela permettra de gérer les erreurs survenant dans les deux fonctions.</p>
<div class="notecard note">
<p><strong>Note :</strong> Il est également possible d'utiliser un bloc <code><a href="/fr/docs/Web/JavaScript/Reference/Statements/try...catch#the_finally_clause">finally</a></code> au sein d'une fonction asynchrone, à la place d'un bloc asynchrone <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally">.finally()</a></code>, pour montrer un état final sur le déroulement de l'opération — vous pouvez voir cela en action dans notre <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/promise-finally-async-await.html">exemple en direct</a> (voir aussi le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/promise-finally-async-await.html">code source</a>).</p>
</div>
<h2 id="handling_asyncawait_slowdown">Gérer les ralentissements potentiellement causés par async/await</h2>
<p>Il est vraiment utile de connaître <code>async</code>/<code>await</code>, mais il y a quelques inconvénients à prendre en compte.</p>
<p><code>async</code>/<code>await</code> donne à votre code une apparence synchrone, et d'une certaine manière, il le fait se comporter de manière plus synchrone. Le mot-clé <code>await</code> bloque l'exécution de tout le code qui le suit jusqu'à ce que la promesse se réalise, exactement comme dans le cas d'une opération synchrone. Il permet certes aux autres tâches de continuer à s'exécuter entre-temps, mais le code attendu est bloqué.</p>
<pre class="brush: js">async function makeResult(items) {
let newArr = [];
for(let i=0; i < items.length; i++) {
newArr.push('word_'+i);
}
return newArr;
}
async function getResult() {
let result = await makeResult(items); // Bloqué sur cette ligne
useThatResult(result); // Pas exécuté tant que makeResult() n'a pas fini
}</pre>
<p>Cela signifie que votre code pourrait être ralenti par un nombre important de promesses attendues se produisant directement les unes après les autres. Chaque <code>await</code> attendra que la précédente se termine, alors qu'en réalité ce que vous voulez, c'est que les promesses commencent à être traitées simultanément, comme elles le feraient si nous n'utilisions pas <code>async</code>/<code>await</code>.</p>
<p>Il existe un modèle qui peut atténuer ce problème - déclencher tous les processus de promesse en stockant les objets <code>Promise</code> dans des variables, et en les attendant tous ensuite. Jetons un coup d'œil à quelques exemples qui prouvent le concept.</p>
<p>Nous disposons de deux exemples - <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/slow-async-await.html">slow-async-await.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/slow-async-await.html">code source</a>) et <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/fast-async-await.html">fast-async-await.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/fast-async-await.html">code source</a>). Les deux commencent par une fonction promise personnalisée qui simule un processus asynchrone avec un appel <code><a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code> :</p>
<pre class="brush: js">function timeoutPromise(interval) {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve("fait");
}, interval);
});
};</pre>
<p>Ensuite, chacun comprend une fonction asynchrone <code>timeTest()</code> qui attend trois appels <code>timeoutPromise()</code> :</p>
<pre class="brush: js">async function timeTest() {
...
}</pre>
<p>Chacune d'entre elles se termine en enregistrant une heure de début, en voyant combien de temps la promesse <code>timeTest()</code> met à se réaliser, puis en enregistrant une heure de fin et en indiquant combien de temps l'opération a pris au total :</p>
<pre class="brush: js">let startTime = Date.now();
timeTest().then(() => {
let finishTime = Date.now();
let timeTaken = finishTime - startTime;
console.log("Temps pris en millisecondes : " + timeTaken);
})</pre>
<p>C'est la fonction <code>timeTest()</code> qui diffère dans chaque cas.</p>
<p>Dans l'exemple <code>slow-async-await.html</code>, <code>timeTest()</code> ressemble à ceci :</p>
<pre class="brush: js">async function timeTest() {
await timeoutPromise(3000);
await timeoutPromise(3000);
await timeoutPromise(3000);
}</pre>
<p>Ici, nous attendons les trois appels <code>timeoutPromise()</code> directement, en faisant en sorte que chacun d'eux alerte pendant 3 secondes. Chaque appel suivant est forcé d'attendre jusqu'à ce que le dernier soit terminé - si vous exécutez le premier exemple, vous verrez la boîte d'alerte signaler une durée d'exécution totale d'environ 9 secondes.</p>
<p>Dans l'exemple <code>fast-async-await.html</code>, <code>timeTest()</code> ressemble à ceci :</p>
<pre class="brush: js">async function timeTest() {
const timeoutPromise1 = timeoutPromise(3000);
const timeoutPromise2 = timeoutPromise(3000);
const timeoutPromise3 = timeoutPromise(3000);
await timeoutPromise1;
await timeoutPromise2;
await timeoutPromise3;
}</pre>
<p>Ici, nous stockons les trois objets <code>Promise</code> dans des variables, ce qui a pour effet de déclencher leurs processus associés, tous exécutés simultanément.</p>
<p>Ensuite, nous attendons leurs résultats - parce que les promesses ont toutes commencé à être traitées essentiellement au même moment, les promesses se réaliseront toutes en même temps ; lorsque vous exécuterez le deuxième exemple, vous verrez la boîte d'alerte indiquant un temps d'exécution total d'un peu plus de 3 secondes !</p>
<h3 id="handling_errors">Gestion des erreurs</h3>
<p>La stratégie précédente a un défaut : on pourrait avoir des erreurs qui ne seraient pas gérées.</p>
<p>Mettons à jour les exemples précédents en ajoutant une promesse rejetée et une instruction <code>catch</code> à la fin :</p>
<pre class="brush: js">function timeoutPromiseResolve(interval) {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve("Succès");
}, interval);
});
};
function timeoutPromiseReject(interval) {
return new Promise((resolve, reject) => {
setTimeout(function(){
reject("Erreur");
}, interval);
});
};
async function timeTest() {
await timeoutPromiseResolve(5000);
await timeoutPromiseReject(2000);
await timeoutPromiseResolve(3000);
}
let startTime = Date.now();
timeTest().then(() => {})
.catch(e => {
console.log(e);
let finishTime = Date.now();
let timeTaken = finishTime - startTime;
console.log("Temps écoulé en millisecondes : " + timeTaken);
})</pre>
<p>Dans l'exemple qui précède, l'erreur est gérée correctement et le message dans la console apparaît après environ 7 secondes.</p>
<p>Voyons maintenant la deuxième approche :</p>
<pre class="brush: js">function timeoutPromiseResolve(interval) {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve("Succès");
}, interval);
});
};
function timeoutPromiseReject(interval) {
return new Promise((resolve, reject) => {
setTimeout(function(){
reject("Erreur");
}, interval);
});
};
async function timeTest() {
const timeoutPromiseResolve1 = timeoutPromiseResolve(5000);
const timeoutPromiseReject2 = timeoutPromiseReject(2000);
const timeoutPromiseResolve3 = timeoutPromiseResolve(3000);
await timeoutPromiseResolve1;
await timeoutPromiseReject2;
await timeoutPromiseResolve3;
}
let startTime = Date.now();
timeTest().then(() => {
}).catch(e => {
console.log(e);
let finishTime = Date.now();
let timeTaken = finishTime - startTime;
console.log("Temps écoulé en millisecondes : " + timeTaken);
})</pre>
<p>Dans cet exemple, on a une erreur qui n'est pas gérée dans la console (après 2 secondes) et le message apparaît après environ 5 secondes.</p>
<p>Pour démarrer les promesses en parallèles et intercepter les erreurs correctement, on pourrait utiliser <code>Promise.all()</code> comme vu auparavant :</p>
<pre class="brush: js">function timeoutPromiseResolve(interval) {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve("Succès");
}, interval);
});
};
function timeoutPromiseReject(interval) {
return new Promise((resolve, reject) => {
setTimeout(function(){
reject("Erreur");
}, interval);
});
};
async function timeTest() {
const timeoutPromiseResolve1 = timeoutPromiseResolve(5000);
const timeoutPromiseReject2 = timeoutPromiseReject(2000);
const timeoutPromiseResolve3 = timeoutPromiseResolve(3000);
const results = await Promise.all([timeoutPromiseResolve1, timeoutPromiseReject2, timeoutPromiseResolve3]);
return results;
}
let startTime = Date.now();
timeTest().then(() => {
}).catch(e => {
console.log(e);
let finishTime = Date.now();
let timeTaken = finishTime - startTime;
console.log("Temps écoulé en millisecondes : " + timeTaken);
})</pre>
<p>Dans cet exemple, l'erreur est gérée correctement après 2 secondes et on a le message dans la console après environ 2 secondes.</p>
<p>La méthode <code>Promise.all()</code> rejète lorsqu'au moins un de ses promesses d'entrée rejète. Si on veut que toutes les promesses soient résolues (correctement ou avec un rejet), on pourra utiliser la méthode <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled"><code>Promise.allSettled()</code></a> à la place.</p>
<h2 id="asyncawait_class_methods">Méthodes de classe async/await</h2>
<p>Une dernière remarque avant de poursuivre, vous pouvez même ajouter <code>async</code> devant les méthodes de classe/objet pour qu'elles renvoient des promesses, et <code>await</code> des promesses à l'intérieur de celles-ci. Jetez un œil au <a href="/fr/docs/Learn/JavaScript/Objects/Inheritance#ecmascript_2015_classes">code de la classe ES que nous avons vu dans notre article sur le JavaScript orienté objet</a>, puis regardez notre version modifiée avec une méthode <code>async</code> :</p>
<pre class="brush: js">class Personne {
constructor(prenom, nomFamille, age, genre, interets) {
this.nom = {
prenom,
nomFamille
};
this.age = age;
this.genre = genre;
this.interets = interets;
}
async salutation() {
return await Promise.resolve(`Bonjour ! Je suis ${this.nom.prenom}`);
};
aurevoir() {
console.log(`${this.nom.prenom} a quitté le bâtiment. À une prochaine fois !`);
};
}
let han = new Personne('Han', 'Solo', 25, 'homme', ['Contrebande']);</pre>
<p>La méthode de la première classe peut maintenant être utilisée de la manière suivante :</p>
<pre class="brush: js">han.salutation().then(console.log);</pre>
<h2 id="browser_support">Prise en charge des navigateurs</h2>
<p>L'une des considérations à prendre en compte pour décider d'utiliser <code>async</code>/<code>await</code>est la prise en charge des anciens navigateurs. Ces fonctionnalités sont disponibles dans les versions modernes de la plupart des navigateurs, tout comme les promesses ; les principaux problèmes de prise en charge concernent Internet Explorer et Opera Mini.</p>
<p>Si vous souhaitez utiliser <code>async</code>/<code>await</code> mais que vous êtes préoccupé par la prise en charge de navigateurs plus anciens, vous pouvez envisager d'utiliser la bibliothèque <a href="https://babeljs.io/">BabelJS</a>. Cela vous permet d'écrire vos applications en utilisant les dernières versions de JavaScript et de laisser Babel déterminer les modifications éventuellement nécessaires pour les navigateurs de vos utilisateurs. Lorsque vous rencontrez un navigateur qui ne supporte pas async/await, le <i>polyfill</i> « prothèse d'émulation » de Babel peut automatiquement fournir des <i>fallbacks</i> « solutions de secours » qui fonctionnent dans les anciens navigateurs.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Et voilà, <code>async</code>/<code>await</code> offre un moyen agréable et simplifié d'écrire du code asynchrone, plus facile à lire et à maintenir. Même si la prise en charge par les navigateurs est plus limitée que d'autres mécanismes de code asynchrone à l'heure où nous écrivons ces lignes, cela vaut la peine de l'apprendre et d'envisager de l'utiliser, maintenant et à l'avenir.</p>
<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Choosing_the_right_approach", "Learn/JavaScript/Asynchronous")}}</p>
<h2 id="in_this_module">Dans ce module</h2>
<ul>
<li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Concepts">Concepts généraux de programmation asynchrone</a></li>
<li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing">Introduction au JavaScript asynchrone</a></li>
<li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asynchrone coopératif : Délais et intervalles</a></li>
<li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Promises">Gérer les opérations asynchrones avec élégance grâce aux Promesses</a></li>
<li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Async_await">Faciliter la programmation asynchrone avec async et await</a></li>
<li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choisir la bonne approche</a></li>
</ul>
|