From faa96e657621455284245018b8a3b5050b613e6b Mon Sep 17 00:00:00 2001 From: julieng Date: Sun, 14 Nov 2021 14:30:47 +0100 Subject: convert content to md --- .../javascript/asynchronous/promises/index.md | 767 +++++++++++---------- 1 file changed, 391 insertions(+), 376 deletions(-) (limited to 'files/fr/learn/javascript/asynchronous/promises') diff --git a/files/fr/learn/javascript/asynchronous/promises/index.md b/files/fr/learn/javascript/asynchronous/promises/index.md index 69f6de6a21..0c3b506ed7 100644 --- a/files/fr/learn/javascript/asynchronous/promises/index.md +++ b/files/fr/learn/javascript/asynchronous/promises/index.md @@ -15,93 +15,94 @@ tags: - then translation_of: Learn/JavaScript/Asynchronous/Promises --- -
{{LearnSidebar}}
+{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}} -
{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}
- -

Les promesses sont une fonctionnalité relativement nouvelle du langage JavaScript qui vous permet de reporter d'autres actions jusqu'à ce qu'une action précédente soit terminée, ou de répondre à son échec. Ceci est utile pour mettre en place une séquence d'opérations asynchrones afin qu'elles fonctionnent correctement. Cet article vous montre comment les promesses fonctionnent, comment vous les verrez utilisées avec les API Web, et comment écrire les vôtres.

+**Les promesses** sont une fonctionnalité relativement nouvelle du langage JavaScript qui vous permet de reporter d'autres actions jusqu'à ce qu'une action précédente soit terminée, ou de répondre à son échec. Ceci est utile pour mettre en place une séquence d'opérations asynchrones afin qu'elles fonctionnent correctement. Cet article vous montre comment les promesses fonctionnent, comment vous les verrez utilisées avec les API Web, et comment écrire les vôtres. - - + + - +
Prérequis :Connaissances informatiques de base, compréhension raisonnable des principes fondamentaux de JavaScript.
+ Connaissances informatiques de base, compréhension raisonnable des + principes fondamentaux de JavaScript. +
Objectif : Comprendre les promesses et savoir comment les utiliser.
-

Que sont les promesses ?

+## Que sont les promesses ? -

Nous avons examiné les promesses (Promise) brièvement dans le premier article du cours, mais ici nous allons les examiner de manière beaucoup plus approfondie.

+Nous avons examiné les [promesses (`Promise`)](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise) brièvement dans le premier article du cours, mais ici nous allons les examiner de manière beaucoup plus approfondie. -

Essentiellement, une promesse est un objet qui représente un état intermédiaire d'une opération - en fait, c'est une promesse qu'un résultat d'une certaine nature sera retourné à un moment donné dans le futur. Il n'y a aucune garantie du moment exact où l'opération se terminera et où le résultat sera renvoyé, mais il est une garantie que lorsque le résultat est disponible, ou que la promesse échoue, le code que vous fournissez sera exécuté afin de faire autre chose avec un résultat réussi, ou de gérer gracieusement un cas d'échec.

+Essentiellement, une promesse est un objet qui représente un état intermédiaire d'une opération - en fait, c'est une _promesse_ qu'un résultat d'une certaine nature sera retourné à un moment donné dans le futur. Il n'y a aucune garantie du moment exact où l'opération se terminera et où le résultat sera renvoyé, mais il _est_ une garantie que lorsque le résultat est disponible, ou que la promesse échoue, le code que vous fournissez sera exécuté afin de faire autre chose avec un résultat réussi, ou de gérer gracieusement un cas d'échec. -

En général, vous êtes moins intéressé par le temps qu'une opération asynchrone prendra pour renvoyer son résultat (à moins bien sûr qu'elle ne prenne beaucoup trop de temps !), et plus intéressé par le fait de pouvoir répondre à son retour, quel que soit le moment. Et bien sûr, il est agréable que cela ne bloque pas le reste de l'exécution du code.

+En général, vous êtes moins intéressé par le temps qu'une opération asynchrone prendra pour renvoyer son résultat (à moins bien sûr qu'elle ne prenne _beaucoup_ trop de temps !), et plus intéressé par le fait de pouvoir répondre à son retour, quel que soit le moment. Et bien sûr, il est agréable que cela ne bloque pas le reste de l'exécution du code. -

L'une des utilisations les plus courantes des promesses concerne les API web qui renvoient une promesse. Considérons une hypothétique application de chat vidéo. L'application dispose d'une fenêtre contenant une liste des amis de l'utilisateur, et un clic sur un bouton à côté d'un utilisateur lance un appel vidéo vers cet utilisateur.

+L'une des utilisations les plus courantes des promesses concerne les API web qui renvoient une promesse. Considérons une hypothétique application de chat vidéo. L'application dispose d'une fenêtre contenant une liste des amis de l'utilisateur, et un clic sur un bouton à côté d'un utilisateur lance un appel vidéo vers cet utilisateur. -

Le gestionnaire de ce bouton appelle getUserMedia() afin d'avoir accès à la caméra et au microphone de l'utilisateur. Puisque getUserMedia() doit s'assurer que l'utilisateur a la permission d'utiliser ces dispositifs et lui demander quel microphone utiliser et quelle caméra utiliser (ou s'il s'agit d'un appel vocal uniquement, parmi d'autres options possibles), il peut bloquer jusqu'à ce que non seulement toutes ces décisions soient prises, mais aussi que la caméra et le microphone soient activés. En outre, l'utilisateur peut ne pas répondre immédiatement à ces demandes d'autorisation. Cela peut potentiellement prendre beaucoup de temps.

+Le gestionnaire de ce bouton appelle [`getUserMedia()`](/fr/docs/Web/API/MediaDevices/getUserMedia) afin d'avoir accès à la caméra et au microphone de l'utilisateur. Puisque `getUserMedia()` doit s'assurer que l'utilisateur a la permission d'utiliser ces dispositifs _et_ lui demander quel microphone utiliser et quelle caméra utiliser (ou s'il s'agit d'un appel vocal uniquement, parmi d'autres options possibles), il peut bloquer jusqu'à ce que non seulement toutes ces décisions soient prises, mais aussi que la caméra et le microphone soient activés. En outre, l'utilisateur peut ne pas répondre immédiatement à ces demandes d'autorisation. Cela peut potentiellement prendre beaucoup de temps. -

Puisque l'appel à getUserMedia() est effectué depuis le processus principal du navigateur, l'ensemble du navigateur est bloqué jusqu'à ce que getUserMedia() retourne une réponse ! Évidemment, ce n'est pas une option viable ; sans les promesses, tout dans le navigateur devient inutilisable jusqu'à ce que l'utilisateur décide ce qu'il faut faire de la caméra et du microphone. Ainsi, au lieu d'attendre l'utilisateur, d'obtenir l'activation des périphériques choisis et de retourner directement le MediaStream pour le flux créé à partir des sources sélectionnées, getUserMedia() retourne une promesse qui est résolue avec le MediaStream une fois qu'il est disponible.

+Puisque l'appel à `getUserMedia()` est effectué depuis le processus principal du navigateur, l'ensemble du navigateur est bloqué jusqu'à ce que `getUserMedia()` retourne une réponse ! Évidemment, ce n'est pas une option viable ; sans les promesses, tout dans le navigateur devient inutilisable jusqu'à ce que l'utilisateur décide ce qu'il faut faire de la caméra et du microphone. Ainsi, au lieu d'attendre l'utilisateur, d'obtenir l'activation des périphériques choisis et de retourner directement le [`MediaStream`](/fr/docs/Web/API/MediaStream) pour le flux créé à partir des sources sélectionnées, `getUserMedia()` retourne une [`promesse`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise) qui est résolue avec le [`MediaStream`](/fr/docs/Web/API/MediaStream) une fois qu'il est disponible. -

Le code qu'utiliserait l'application de chat vidéo pourrait ressembler à ceci :

+Le code qu'utiliserait l'application de chat vidéo pourrait ressembler à ceci : -
function handleCallButton(evt) {
+```js
+function handleCallButton(evt) {
   setStatusMessage("Appel...");
   navigator.mediaDevices.getUserMedia({video: true, audio: true})
-    .then(chatStream => {
+    .then(chatStream => {
       selfViewElem.srcObject = chatStream;
-      chatStream.getTracks().forEach(track => myPeerConnection.addTrack(track, chatStream));
+      chatStream.getTracks().forEach(track => myPeerConnection.addTrack(track, chatStream));
       setStatusMessage("Connecté");
-    }).catch(err => {
+    }).catch(err => {
       setStatusMessage("Échec de la connexion");
     });
 }
-
+``` -

Cette fonction commence par utiliser une fonction appelée setStatusMessage() pour mettre à jour un affichage d'état avec le message "Appel...", indiquant qu'un appel est tenté.Il appelle ensuite getUserMedia(), demandant un flux qui a à la fois des pistes vidéo et audio, puis une fois que cela a été obtenu, configure un élément vidéo pour montrer le flux provenant de la caméra comme une "vue de soi", puis prend chacune des pistes du flux et les ajoute à la RTCPeerConnection WebRTC représentant une connexion à un autre utilisateur. Après cela, l'affichage de l'état est mis à jour pour indiquer "Connecté".

+Cette fonction commence par utiliser une fonction appelée `setStatusMessage()` pour mettre à jour un affichage d'état avec le message "Appel...", indiquant qu'un appel est tenté.Il appelle ensuite `getUserMedia()`, demandant un flux qui a à la fois des pistes vidéo et audio, puis une fois que cela a été obtenu, configure un élément vidéo pour montrer le flux provenant de la caméra comme une "vue de soi", puis prend chacune des pistes du flux et les ajoute à la [`RTCPeerConnection`](/fr/docs/Web/API/RTCPeerConnection) [WebRTC](/fr/docs/Web/API/WebRTC_API) représentant une connexion à un autre utilisateur. Après cela, l'affichage de l'état est mis à jour pour indiquer "Connecté". -

Si getUserMedia() échoue, le bloc catch s'exécute. Celui-ci utilise setStatusMessage() pour mettre à jour la case d'état afin d'indiquer qu'une erreur s'est produite.

+Si `getUserMedia()` échoue, le bloc `catch` s'exécute. Celui-ci utilise `setStatusMessage()` pour mettre à jour la case d'état afin d'indiquer qu'une erreur s'est produite. -

La chose importante ici est que l'appel getUserMedia() revient presque immédiatement, même si le flux de la caméra n'a pas encore été obtenu. Même si la fonction handleCallButton() est déjà retournée au code qui l'a appelée, lorsque getUserMedia() a fini de travailler, elle appelle le gestionnaire que vous fournissez. Tant que l'application ne suppose pas que le flux a commencé, elle peut continuer à fonctionner.

+La chose importante ici est que l'appel `getUserMedia()` revient presque immédiatement, même si le flux de la caméra n'a pas encore été obtenu. Même si la fonction `handleCallButton()` est déjà retournée au code qui l'a appelée, lorsque `getUserMedia()` a fini de travailler, elle appelle le gestionnaire que vous fournissez. Tant que l'application ne suppose pas que le flux a commencé, elle peut continuer à fonctionner. -
-

Note : Vous pouvez en apprendre davantage sur ce sujet quelque peu avancé, si cela vous intéresse, dans l'article L'essentiel du WebRTC. Un code similaire à celui-ci, mais beaucoup plus complet, est utilisé dans cet exemple.

-
+> **Note :** Vous pouvez en apprendre davantage sur ce sujet quelque peu avancé, si cela vous intéresse, dans l'article [L'essentiel du WebRTC](/fr/docs/Web/API/WebRTC_API/Signaling_and_video_calling). Un code similaire à celui-ci, mais beaucoup plus complet, est utilisé dans cet exemple. -

Le problème des fonctions de rappel

+## Le problème des fonctions de rappel -

Pour bien comprendre pourquoi les promesses sont une bonne chose, il est utile de repenser aux anciennes fonctions de rappel (callback) et de comprendre pourquoi elles sont problématiques.

+Pour bien comprendre pourquoi les promesses sont une bonne chose, il est utile de repenser aux anciennes fonctions de rappel (_callback_) et de comprendre pourquoi elles sont problématiques. -

Prenons l'exemple de la commande d'une pizza. Il y a certaines étapes que vous devez franchir pour que votre commande soit réussie, et cela n'a pas vraiment de sens d'essayer de les exécuter dans le désordre, ou dans l'ordre mais avant que chaque étape précédente ne soit tout à fait terminée :

+Prenons l'exemple de la commande d'une pizza. Il y a certaines étapes que vous devez franchir pour que votre commande soit réussie, et cela n'a pas vraiment de sens d'essayer de les exécuter dans le désordre, ou dans l'ordre mais avant que chaque étape précédente ne soit tout à fait terminée : -
    -
  1. Vous choisissez les garnitures que vous voulez. Cela peut prendre un certain temps si vous êtes indécis, et peut échouer si vous n'arrivez pas à vous décider, ou si vous décidez de prendre un curry à la place.
  2. -
  3. Vous passez ensuite votre commande. Le retour d'une pizza peut prendre un certain temps et peut échouer si le restaurant ne dispose pas des ingrédients nécessaires à sa cuisson.
  4. -
  5. Vous récupérez ensuite votre pizza et la mangez. Cela peut échouer si, par exemple, vous avez oublié votre portefeuille et ne pouvez pas payer la pizza !
  6. -
+1. Vous choisissez les garnitures que vous voulez. Cela peut prendre un certain temps si vous êtes indécis, et peut échouer si vous n'arrivez pas à vous décider, ou si vous décidez de prendre un curry à la place. +2. Vous passez ensuite votre commande. Le retour d'une pizza peut prendre un certain temps et peut échouer si le restaurant ne dispose pas des ingrédients nécessaires à sa cuisson. +3. Vous récupérez ensuite votre pizza et la mangez. Cela peut échouer si, par exemple, vous avez oublié votre portefeuille et ne pouvez pas payer la pizza ! -

Avec l'ancien modèle de rappels, une représentation en pseudo-code de la fonctionnalité ci-dessus pourrait ressembler à quelque chose comme ceci :

+Avec l'ancien modèle de [rappels](/fr/docs/Learn/JavaScript/Asynchronous/Introducing#callbacks), une représentation en pseudo-code de la fonctionnalité ci-dessus pourrait ressembler à quelque chose comme ceci : -
chooseToppings(function(toppings) {
+```js
+chooseToppings(function(toppings) {
   placeOrder(toppings, function(order) {
     collectOrder(order, function(pizza) {
       eatPizza(pizza);
     }, failureCallback);
   }, failureCallback);
-}, failureCallback);
+}, failureCallback); +``` -

Cela est désordonné et difficile à lire (souvent appelé « callback hell »), nécessite que le failureCallback() soit appelé plusieurs fois (une fois pour chaque fonction imbriquée), avec d'autres problèmes en plus.

+Cela est désordonné et difficile à lire (souvent appelé « [_callback hell_](http://callbackhell.com/) »), nécessite que le `failureCallback()` soit appelé plusieurs fois (une fois pour chaque fonction imbriquée), avec d'autres problèmes en plus. -

Améliorations avec des promesses

+### Améliorations avec des promesses -

Les promesses facilitent grandement l'écriture, l'analyse et l'exécution de situations telles que celle décrite ci-dessus. Si nous avions représenté le pseudo-code ci-dessus en utilisant des promesses asynchrones à la place, nous aurions obtenu quelque chose comme ceci :

+Les promesses facilitent grandement l'écriture, l'analyse et l'exécution de situations telles que celle décrite ci-dessus. Si nous avions représenté le pseudo-code ci-dessus en utilisant des promesses asynchrones à la place, nous aurions obtenu quelque chose comme ceci : -
chooseToppings()
+```js
+chooseToppings()
 .then(function(toppings) {
   return placeOrder(toppings);
 })
@@ -111,322 +112,337 @@ translation_of: Learn/JavaScript/Asynchronous/Promises
 .then(function(pizza) {
   eatPizza(pizza);
 })
-.catch(failureCallback);
+.catch(failureCallback); +``` -

C'est bien mieux - il est plus facile de voir ce qui se passe, nous n'avons besoin que d'un seul bloc .catch() pour gérer toutes les erreurs, cela ne bloque pas le processus principal (nous pouvons donc continuer à jouer à des jeux vidéo en attendant que la pizza soit prête à être collectée), et chaque opération a la garantie d'attendre que les opérations précédentes soient terminées avant de s'exécuter. Nous sommes en mesure d'enchaîner plusieurs actions asynchrones pour qu'elles se produisent les unes après les autres de cette façon, car chaque bloc .then() renvoie une nouvelle promesse qui se résout lorsque le bloc .then() a fini de s'exécuter. Astucieux, non ?

+C'est bien mieux - il est plus facile de voir ce qui se passe, nous n'avons besoin que d'un seul bloc `.catch()` pour gérer toutes les erreurs, cela ne bloque pas le processus principal (nous pouvons donc continuer à jouer à des jeux vidéo en attendant que la pizza soit prête à être collectée), et chaque opération a la garantie d'attendre que les opérations précédentes soient terminées avant de s'exécuter. Nous sommes en mesure d'enchaîner plusieurs actions asynchrones pour qu'elles se produisent les unes après les autres de cette façon, car chaque bloc `.then()` renvoie une nouvelle promesse qui se résout lorsque le bloc `.then()` a fini de s'exécuter. Astucieux, non ? -

En utilisant les fonctions flèches, vous pouvez simplifier encore plus le code :

+En utilisant les fonctions flèches, vous pouvez simplifier encore plus le code : -
chooseToppings()
-.then(toppings =>
+```js
+chooseToppings()
+.then(toppings =>
   placeOrder(toppings)
 )
-.then(order =>
+.then(order =>
   collectOrder(order)
 )
-.then(pizza =>
+.then(pizza =>
   eatPizza(pizza)
 )
-.catch(failureCallback);
- -

Ou encore ça :

- -
chooseToppings()
-.then(toppings => placeOrder(toppings))
-.then(order => collectOrder(order))
-.then(pizza => eatPizza(pizza))
-.catch(failureCallback);
- -

Cela fonctionne car avec les fonctions flèches () => x est un raccourci valide pour () => { return x ; }.

- -

Vous pourriez même le faire ainsi, puisque les fonctions ne font que passer leurs arguments directement, et qu'il n'y a donc pas besoin de cette couche supplémentaire de fonctions :

- -
chooseToppings().then(placeOrder).then(collectOrder).then(eatPizza).catch(failureCallback);
- -

Cependant, la lecture n'est pas aussi facile et cette syntaxe peut ne pas être utilisable si vos blocs sont plus complexes que ce que nous avons montré ici.

- -
-

Note : Vous pouvez apporter d'autres améliorations avec la syntaxe async/await, que nous aborderons dans le prochain article.

-
- -

Dans leur forme la plus basique, les promesses sont similaires aux écouteurs d'événements, mais avec quelques différences :

- - - -

Explication de la syntaxe de base des promesses : exemple concret

- -

Il est important de comprendre les promesses, car la plupart des API Web modernes les utilisent pour les fonctions qui exécutent des tâches potentiellement longues. Pour utiliser les technologies Web modernes, vous devrez utiliser des promesses. Plus loin dans ce chapitre, nous verrons comment écrire votre propre promesse, mais pour l'instant, nous allons nous pencher sur quelques exemples simples que vous rencontrerez dans les API Web.

- -

Dans le premier exemple, nous allons utiliser la méthode fetch() pour récupérer une image sur le web, la méthode blob() pour transformer le contenu brut du corps de la réponse fetch en un objet Blob, puis afficher ce blob à l'intérieur d'un élément <img>. Cet exemple est très similaire à celui que nous avons examiné dans le premier article, mais nous le ferons un peu différemment au fur et à mesure que nous vous ferons construire votre propre code basé sur des promesses.

- -
-

Note : L'exemple suivant ne fonctionnera pas si vous l'exécutez directement à partir du fichier (c'est-à-dire via une URL file://). Vous devez l'exécuter via un serveur de test local, ou utiliser une solution en ligne telle que Glitch ou les pages GitHub.

-
- -
    -
  1. -

    Tout d'abord, téléchargez notre modèle HTML simple et le fichier image que nous allons récupérer.

    -
  2. -
  3. -

    Ajoutez un élément <script> au bas de l'élément HTML <body>.

    -
  4. -
  5. -

    À l'intérieur de votre élément <script>, ajoutez la ligne suivante :

    -
    let promise = fetch('coffee.jpg');
    -

    Cela appelle la méthode fetch(), en lui passant en paramètre l'URL de l'image à récupérer sur le réseau. Cette méthode peut également prendre un objet d'options comme second paramètre facultatif, mais nous n'utilisons que la version la plus simple pour le moment. Nous stockons l'objet promesse retourné par fetch() à l'intérieur d'une variable appelée promise. Comme nous l'avons dit précédemment, cet objet représente un état intermédiaire qui n'est initialement ni un succès ni un échec - le terme officiel pour une promesse dans cet état est en attente (pending en anglais).

    -
  6. -
  7. -

    Pour répondre à l'achèvement réussi de l'opération lorsque cela se produit (dans ce cas, lorsqu'une réponse est retournée), nous invoquons la méthode .then() de l'objet promesse. La fonction de rappel à l'intérieur du bloc .then() s'exécute uniquement lorsque l'appel de la promesse se termine avec succès et retourne l'objet Response — en langage de promesse, lorsqu'elle a été remplie (fullfilled en anglais). On lui passe l'objet Response retourné en tant que paramètre.

    -
    -

    Note : Le fonctionnement d'un bloc .then() est similaire à celui de l'ajout d'un écouteur d'événements à un objet à l'aide de AddEventListener(). Il ne s'exécute pas avant qu'un événement ne se produise (lorsque la promesse se réalise). La différence la plus notable est qu'un .then() ne s'exécutera qu'une fois à chaque fois qu'il sera utilisé, alors qu'un écouteur d'événements pourrait être invoqué plusieurs fois.

    -
    -

    Nous exécutons immédiatement la méthode blob() sur cette réponse pour nous assurer que le corps de la réponse est entièrement téléchargé, et lorsqu'il est disponible, le transformer en un objet Blob avec lequel nous pouvons faire quelque chose. Le résultat de cette méthode est retourné comme suit :

    -
    response => response.blob()
    -

    qui est un raccourci de

    -
    function(response) {
    -  return response.blob();
    -}
    -

    Malheureusement, nous devons faire un peu plus que cela. Les promesses de récupération n'échouent pas sur les erreurs 404 ou 500 - seulement sur quelque chose de catastrophique comme une panne de réseau. Au lieu de cela, elles réussissent, mais avec la propriété response.ok définie à false. Pour produire une erreur sur un 404, par exemple, nous devons vérifier la valeur de response.ok, et si c'est false, lancer une erreur, ne renvoyant le blob que si elle est à true. Cela peut être fait comme suit - ajoutez les lignes suivantes sous votre première ligne de JavaScript.

    -
    let promise2 = promise.then(response => {
    -  if (!response.ok) {
    -    throw new Error(`erreur HTTP ! statut : ${response.status}`);
    -  } else {
    -    return response.blob();
    -  }
    -});
    -
  8. -
  9. -

    Chaque appel à la méthode .then() crée une nouvelle promesse. Ceci est très utile ; parce que la méthode blob() renvoie également une promesse, nous pouvons manipuler l'objet Blob qu'elle renvoie sur l'accomplissement en invoquant la méthode .then() de la seconde promesse. Parce que nous voulons faire quelque chose d'un peu plus complexe au blob que de simplement exécuter une seule méthode sur lui et renvoyer le résultat, nous devrons envelopper le corps de la fonction dans des accolades cette fois (sinon, ça lancera une erreur).

    -

    Ajoutez ce qui suit à la fin de votre code :

    -
    let promise3 = promise2.then(myBlob => {
    -})
    -
  10. -
  11. -

    Maintenant, remplissons le corps de la fonction de rappel .then(). Ajoutez les lignes suivantes à l'intérieur des accolades :

    -
    let objectURL = URL.createObjectURL(myBlob);
    -let image = document.createElement('img');
    -image.src = objectURL;
    -document.body.appendChild(image);
    -

    Nous exécutons ici la méthode URL.createObjectURL(), en lui passant en paramètre le Blob renvoyé lors de la réalisation de la deuxième promesse. Cela permettra de renvoyer une URL pointant vers l'objet. Ensuite, nous créons un élément <img>, définissons son attribut src comme étant égal à l'URL de l'objet et l'ajoutons au DOM, de sorte que l'image s'affiche sur la page !

    -
  12. -
- -

Si vous enregistrez le fichier HTML que vous venez de créer et le chargez dans votre navigateur, vous verrez que l'image s'affiche dans la page comme prévu. Bon travail !

- -
-

Note : Vous remarquerez probablement que ces exemples sont quelque peu artificiels. Vous pourriez tout simplement vous passer de toute la chaîne fetch() et blob(), et simplement créer un élément <img> et définir la valeur de son attribut src à l'URL du fichier image, coffee.jpg. Nous avons toutefois choisi cet exemple parce qu'il démontre les promesses d'une manière simple et agréable, plutôt que pour sa pertinence dans le monde réel.

-
- -

Réagir à un échec

- -

Il manque quelque chose — actuellement, il n'y a rien pour gérer explicitement les erreurs si l'une des promesses échoue (rejects, en anglais). Nous pouvons ajouter la gestion des erreurs en exécutant la méthode .catch() de la promesse précédente. Ajoutez ceci maintenant :

- -
let errorCase = promise3.catch(e => {
+.catch(failureCallback);
+```
+
+Ou encore ça :
+
+```js
+chooseToppings()
+.then(toppings => placeOrder(toppings))
+.then(order => collectOrder(order))
+.then(pizza => eatPizza(pizza))
+.catch(failureCallback);
+```
+
+Cela fonctionne car avec les fonctions flèches `() => x` est un raccourci valide pour `() => { return x ; }`.
+
+Vous pourriez même le faire ainsi, puisque les fonctions ne font que passer leurs arguments directement, et qu'il n'y a donc pas besoin de cette couche supplémentaire de fonctions :
+
+```js
+chooseToppings().then(placeOrder).then(collectOrder).then(eatPizza).catch(failureCallback);
+```
+
+Cependant, la lecture n'est pas aussi facile et cette syntaxe peut ne pas être utilisable si vos blocs sont plus complexes que ce que nous avons montré ici.
+
+> **Note :** Vous pouvez apporter d'autres améliorations avec la syntaxe `async`/`await`, que nous aborderons dans le prochain article.
+
+Dans leur forme la plus basique, les promesses sont similaires aux écouteurs d'événements, mais avec quelques différences :
+
+- Une promesse ne peut réussir ou échouer qu'une seule fois. Elle ne peut pas réussir ou échouer deux fois et elle ne peut pas passer du succès à l'échec ou vice versa une fois l'opération terminée.
+- Si une promesse a réussi ou échoué et que vous ajoutez plus tard une de rappel de réussite/échec, la bonne fonction de rappel sera appelée, même si l'événement a eu lieu plus tôt.
+
+## Explication de la syntaxe de base des promesses : exemple concret
+
+Il est important de comprendre les promesses, car la plupart des API Web modernes les utilisent pour les fonctions qui exécutent des tâches potentiellement longues. Pour utiliser les technologies Web modernes, vous devrez utiliser des promesses. Plus loin dans ce chapitre, nous verrons comment écrire votre propre promesse, mais pour l'instant, nous allons nous pencher sur quelques exemples simples que vous rencontrerez dans les API Web.
+
+Dans le premier exemple, nous allons utiliser la méthode [`fetch()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/fetch) pour récupérer une image sur le web, la méthode [`blob()`](/fr/docs/Web/API/Body/blob) pour transformer le contenu brut du corps de la réponse fetch en un objet [`Blob`](/fr/docs/Web/API/Blob), puis afficher ce blob à l'intérieur d'un élément [``](/fr/docs/Web/HTML/Element/Img). Cet exemple est très similaire à celui que nous avons examiné dans le [premier article](/fr/docs/Learn/JavaScript/Asynchronous/Introducing#asynchronous_javascript), mais nous le ferons un peu différemment au fur et à mesure que nous vous ferons construire votre propre code basé sur des promesses.
+
+> **Note :** L'exemple suivant ne fonctionnera pas si vous l'exécutez directement à partir du fichier (c'est-à-dire via une URL `file://`). Vous devez l'exécuter via un [serveur de test local](/fr/docs/Learn/Common_questions/set_up_a_local_testing_server), ou utiliser une solution en ligne telle que [Glitch](https://glitch.com/) ou [les pages GitHub](/fr/docs/Learn/Common_questions/Using_Github_pages).
+
+1.  Tout d'abord, téléchargez notre [modèle HTML simple](https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html) et le [fichier image](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/coffee.jpg) que nous allons récupérer.
+2.  Ajoutez un élément [`