Promise
Dans les versions anciennes de JS, on se trouvait souvent dans la situation de callback hell ... c'est-à-dire, dans un callback, on fait encore une opération asynchrone, et ainsi de suite. Notre code ressemblait au suivant :
var floppy = require('floppy');
floppy.load('disk',function(data) {
floppy. load ('disk', function (data) {
floppy. load ('disk', function(data) {
floppy.load('disk',function(data) {
floppy. load('disk', function (data) {
floppy.load('disk',function(data) {
floppy. load('disk', function (data) {
floppy.load('disk',function(data) {
});
});
});
});
});
});
});
});Afin de contourner ce problème, la notion de Promise a été développée au fil des années :
Une Promise est un objet qui pourrait produire soit une valeur dans le futur, soit une raison pourquoi elle n'aurait pas pu terminer.
Une Promise est essentiellement un constructor qui va retourner un object qui contient 3 fonctions :
then: une fonction qui prend un callback comme paramètre. Quand la Promise termine (avec succès), le callback passé sera invoqué.catch: une fonction qui prend un callback comma paramètre. Si jamais il y a une erreur ou une exception, ce callback sera invoqué à la place de celui dethenfinally: une fonction qui prend un callback comma paramètre. Ce callback sera systématiquement appelé après lethenou lecatch.
En construisant une Promise, nous passons un callback comme paramètre qui prend 2 paramètres :
la référence à une fonction
resolve, à invoquer quand notre longue opération est complètela référence à une fonction
reject, à appeler dans le cas d'une erreur
L'exemple suivant démontre la construction d'une Promise :
Ici, on attend 1 seconde avant de résoudre la Promise. Regardez comment on invoque le callback resolve seulement dans le callback de l'opération setTimeout. Dans le cas d'une erreur, on invoque plutôt le callback reject.
Ce code fonctionnera tout seul, mais à priori, on aimerait enchaîner des opérations asynchrones après. On le fait avec la fonction then qui nous permet de préciser le callback à invoquer quand la Promise précédent se résout.
Faites attention à retenir cette structure, parce que c'est la fondation pour la suite.
Nous allons essayer de charger un fichier de façon asynchrone avec les Promises :
On lance ce code avec ts-node :
Notez qu'on ne charge pas le 3ème fichier puisque le 2ème n'existe pas. Le faite qu'une erreur soit rencontré fait que la chaîne de Promise est cassé, on saute directement dans la fonction catch.
Async / await
Vous avez sûrement remarqué que ce n'est pas très propre cet enchaînement de Promises (même si c'est mieux que callback hell).
Enchaîner les then crée quand même du code chargé de callbacks, donc on a intégré du "syntactic sugar" (syntax sucré) qui permet d'exprimer une suite de Promise plus brièvement.
D'abord, on marque une fonction avec le mot clé async :
Voici notre chargement de fichier modifié avec async/await.
Il y a 2 choses à retenir :
En marquant une fonction
async, on dit que notre fonction retourne un objet de type "Promise". Ceci se voit avec typescript et VSCode.Le mot clé
awaitfait l'équivalent de ".then", et peut être utilisé sur toutes les Promises.
De plus en plus de librairies offre des alternatifs aux callbacks en utilisant les Promises. Par exemple, la librairie fs fournit un alternatif compatible aux Promises :
Exercice
Enveloppez la fonction "setTimeout" dans une fonction qui s'appelle wait(seconds: number), qui prend comme valeur le nombre de secondes à attendre avant de continuer.
Ensuite, utilisez cette fonction à plusieurs reprises afin rythmer bien l'émission des valeurs sur le stdout (le rythme de la symphonie n° 5 de Beethoven) :
Da - pause (0,33s) - Da - pause (0,33s) - Da - pause (0,33s) - Daaaaaaaaaa - pause (3s) etc.
Mis à jour