Javascript (22) - Les promesses (Objet Promise)

Dans cette leçon, le formateur explique en détail le concept de promesse en JavaScript, en soulignant son rôle central dans la programmation asynchrone grâce à la boucle d'événements. Il montre comment créer une promesse avec le constructeur `Promise`, décrit les trois états (pending, fulfilled, rejected) et le rôle des fonctions `resolve` et `reject`. Un exemple concret génère un nombre aléatoire et résout ou rejette la promesse selon la parité du nombre, illustrant la différence entre la propriété `value` (en cas de succès) et `reason` (en cas d’échec). Le cours détaille ensuite l’utilisation de `then` pour gérer les résolutions, de `catch` pour les rejets, et montre comment chaîner plusieurs `then`/`catch` afin de propager des valeurs d’une étape à l’autre. Enfin, il mentionne les limites de la chaîne de promesses en termes de lisibilité et introduit brièvement l’alternative `async/await` qui sera abordée dans une prochaine vidéo.
Chapters
Bonjour à tous et bienvenue dans cette nouvelle leçon de JavaScript. Aujourd'hui nous allons voir les promesses. Si vous demandez aux programmeurs JavaScript quelle est la meilleure chose qu'ECMAScript 2015 ou ES6 a apporté, ils vous répondront certainement d'une seule voix: les promesses. En effet, les promesses constituent une révolution en ce qui concerne la manière avec laquelle le moteur JavaScript exécute le code. En tirant profit de sa fameuse boucle d'évènements qui permet d'agencer l'exécution des fonctions. D'autant plus pour exécuter des tâches asynchrones qui nécessitent l'attente des résultats avant d'exécuter une tâche spécifique tout en donnant la main au reste du code de s'exécuter. Ce qui donne au JavaScript son caractère non bloquant vis-à-vis des tâches qui dépendent de tiers, comme un serveur ou une API. Comme son nom l'indique, une promesse est un objet JavaScript qui renvoie non pas une valeur à l'instant même, mais une promesse de cette valeur-là. Et c'est au moment où cette dernière est disponible qu'elle sera transmise au code pour poursuivre son exécution. À titre d'exemple, imaginons que vous voulez interroger une base de données afin d'en extraire des informations nécessaires à l'exécution d'un traitement. Comme vous l'aurez deviné, ces données-là mettront un certain temps pour qu'elles parviennent au script. Cependant, seulement la partie du code qui dépend de ces données-là sera mise en attente, alors que le reste du code poursuivra son exécution normalement. Un traitement pareil n'est pas nouveau en JavaScript. En effet, on faisait déjà cela à l'aide du fameux objet XMLHttpRequest invoqué en AJAX. Mais bien que le concept ne soit pas nouveau, son implémentation à l'aide des promesses constitue une grande avancée en termes de programmation asynchrone. Dans cette vidéo, nous allons voir comment utiliser les promesses avec des exemples simples. Toutefois, nous aurons prochainement l'occasion de révéler toute leur puissance avec des cas réels en les mettant en pratique avec l'API Fetch ou dans l'environnement d'exécution Node.js par exemple. Nous allons créer une promesse qui s'appelle p à l'aide du constructeur Promise. Ce constructeur accepte une fonction en guise d'argument. Je vais la déclarer de manière fléchée comme ceci et je mettrai rien dans son corps. Je vais plutôt afficher la variable p dans la console. Regardons ce que ça donne. Ça me donne Promise et si on déplie, l'état de la promesse est Pending. En fait, une promesse a 3 états, à savoir Pending, autrement dit en attente, Fulfilled pour dire la promesse est honorée, ou bien Rejected pour dire que la promesse a échoué. Puisque j'ai rien mis dans le corps de la promesse, donc elle est toujours en cours d'attente. La promesse accepte une fonction en guise d'argument, mais cette fonction elle aussi a des arguments, et précisément 2 arguments qui sont aussi des fonctions que l'on appellera Resolve et Reject. Bien entendu, vous n'êtes pas obligé de respecter ces termes, mais ce sont les noms les plus utilisés au milieu des programmeurs JavaScript. Resolve et Reject sont en fait des fonctions. Alors regardez, on a passé des fonctions en guise d'arguments à une autre fonction, ce qui fait de ces deux fonctions Resolve et Reject des fonctions de rappel ou bien des callbacks. Maintenant, essayons de générer un nombre aléatoire compris entre 0 et 10. On mettra par exemple nbr. Alors cette instruction va générer un nombre aléatoire compris entre 0 et 10 que l'on mettra dans la variable nbr. Maintenant vérifions la parité de ce nombre. On mettra par exemple si nbr est pair, dans ce cas j'appelle la fonction resolve. À laquelle je passe comme argument une chaîne de caractères si vous voulez. Par exemple, on mettra nombre pair. Sinon, dans ce cas, on appelle la fonction reject avec comme argument la chaîne nombre impair. Donc vous l'aurez compris, à l'intérieur de la promesse, on va exécuter soit la fonction resolve si ce que nous attendons est exécuté correctement, ou ou bien reject en cas d'erreur. Dans un cas pratique, ça pourrait par exemple être l'interrogation d'une base de données. Dans ce cas, si la base nous renvoie le résultat correctement, on va exécuter resolve, sinon on exécute reject. Mais en attendant ces 2 résultats, la promesse est dans l'état pending ou bien l'état en attente. Exécutons maintenant ce code. On va toujours afficher dans la console la valeur de p qui n'est rien d'autre que la promesse que nous avons instanciée avec le constructeur Promise. Et là, ça nous affiche toujours une promesse avec l'état fulfilled pour dire que la promesse a été honorée. Et la valeur c'est nombre pair. Alors notez bien ces deux propriétés state et value. Dans ce cas de state c'est l'état, ça peut être soit pending, fulfilled ou bien rejected. Et value c'est la valeur qui est renvoyée par la fonction resolve. Mais au cas où c'est la fonction reject qui est renvoyée, dans ce cas value se transforme en reason ou bien la raison. Voilà on va actualiser plusieurs fois pour générer un nombre impair pour voir la raison. Voilà comme c'est le cas ici. Dans ce cas l'état c'est rejected. Et la raison c'est nombre impair. Alors en cas de succès c'est une valeur, en cas d'échec c'est une raison. Et bien sûr vous avez remarqué que j'ai pas rattrapé la promesse, ça nous rappelle un petit peu le fonctionnement de try-catch. Alors maintenant que notre promesse a été créée, il est temps de la traiter. C'est-à-dire on va voir si le nombre est pair, on va faire un traitement. Dans ce cas on exécute la fonction resolve à la suite de laquelle on va exécuter un traitement personnalisé. Ou bien en cas d'échec, c'est-à-dire si reject est exécuté, dans ce cas on va faire un traitement alternatif. On peut faire ceci: la variable p qui n'est rien d'autre que la promesse, point la méthode then. En fait, la méthode then va s'exécuter en cas de succès, c'est-à-dire si la promesse renvoie l'état fulfilled, ou bien si resolve est exécuté dans ce cas, qui n'est rien d'autre que le premier argument de la fonction. Il faut savoir que then aussi renvoie une promesse et comme argument il accepte une fonction de rappel aussi, c'est-à-dire un callback. Qu'on va écrire de manière fléchée pour simplifier l'écriture. Et cette fonction de callback doit accueillir un argument, on va l'appeler par exemple val pour dire valeur si vous voulez. Maintenant on va afficher cette valeur, on mettra console.log. En fait cette valeur n'est rien d'autre que la valeur qui a été renvoyée au moment de l'appel de resolve. Notez bien que then s'exécute suite à resolve. Alors exécutons maintenant le code. Là c'est un nombre impair alors den n'est pas exécuté. Toujours. Maintenant c'est pair alors den est exécuté et il a affiché nombre pair. Maintenant le cas contraire, c'est-à-dire si le eject est exécuté, autrement dit si le nombre qui a été généré est impair, on va tout simplement mettre .catch. Alors c'est la même syntaxe que try-catch pour gérer les erreurs en JavaScript. Catch aussi a comme argument une fonction de rappel. Que je vais écrire de manière fléchée aussi pour simplifier l'écriture, et comme argument je mettrai aussi val. Alors vous l'aurez deviné, val n'est rien d'autre que le message qui sera renvoyé avec la fonction reject. Et là je mettrai console.log. Réexécutons. Maintenant le nombre est pair et ça me donne le message approprié. Et là c'est nombre impair et j'ai plus d'erreur parce que j'ai pu rattraper la promesse et afficher nombre impair. Il faut savoir que l'on peut procéder à un raccourci pour écrire tout cela, c'est-à-dire au lieu de mettre p., je vais directement la coller avec la promesse comme ça, mais là j'enlève le p., c'est-à-dire je crée directement l'instance de la promesse. Ensuite je vais vérifier si c'est resolve qui est exécutée, à la suite de laquelle j'exécute la méthode then, sinon c'est la méthode catch. Réexécutons, ça donne le même résultat, mais l'erreur qui est là est due à la console.log qu'on a mis à la dernière ligne. Alors je vais commenter ce code. Donc ça me donne nombre pair et là c'est nombre impair, c'est-à-dire que les deux cas sont bien gérés. Il y a aussi ce que l'on appelle le chaînage des promesses, c'est-à-dire que l'on aura une chaîne de then qui se succèdent ou même de catch. Par exemple ici on va intercaler un autre then et ça va accueillir une fonction de rappel comme d'habitude. Donc nous avons deux then qui se suivent, la première then va afficher le message nombre pair et la deuxième then elle va aussi accueillir un argument que j'appellerai aussi val mais Mais dans ce cas de val, il doit être retourné par le then immédiatement précédent, c'est-à-dire celui-ci. Alors je dois retourner quelque chose. Return, par exemple, je confirme, c'est bien pair. C'est-à-dire si jamais c'est le resolve qui est exécuté, dans ce cas on va afficher nombre pair et juste après on retourne le résultat je confirme c'est bien pair. Et ce message sera passé en guise d'argument du prochain then et là je vais l'afficher dans la console. Le val qui est là correspond au dernier message qui a été retourné. Réexécutons. Alors nombre pair, je confirme c'est bien pair. Et si le nombre est impair, alors dans ce cas je m'arrête au premier bloc catch qui est rencontré. Pour le bloc catch aussi je peux chaîner comme ça. Then, je mettrai aussi une callback. En guise d'argument et qui va accueillir la valeur value aussi si vous souhaitez, mais il faut retourner quelque chose juste avant parce que toujours le then dépend du dernier bloc auquel il est attaché. Dans ce cas, je mettrai little, oui c'est bien impair. Donc là, c'est le message que l'on va envoyer et qui va être traité dans le bloc then. Alors exécutons. Alors si le nombre est pair, on affiche je confirme, c'est bien pair. Et s'il est impair, on confirme avec un deuxième message qui dit oui, c'est bien impair. Bien entendu, on peut toujours continuer à chaîner les then et les catch comme on souhaite, c'est-à-dire si vous avez beaucoup de traitements qui dépendent les uns des autres, on peut utiliser cette pratique, mais en abuser, ça présente un petit problème, surtout en ce qui concerne la clarté du code. C'est pourquoi il existe une autre méthode qui permet de toujours prendre en considération les promesses mais en utilisant des fonctions asynchrones principalement à l'aide des mots-clés async et await et on verra comment tout cela fonctionne prochainement. Merci pour votre attention et à la vidéo prochaine.
More from Yamossoun

Algorithme de calcule de la racine carrée par dichotomie #dichotomy #squareroot #algorithm









