Articles

Une introduction rapide à « Promises » et « Async/Await » (avec de nouvelles fonctionnalités)

Une promesse est une instance (objet) de la classe Promise (constructeur). Pour créer une promesse, nous utilisons la syntaxe new Promise(executor) et fournissons une fonction d’exécuteur comme argument. Cette fonction d’exécuteur fournit un moyen de contrôler le comportement de résolution ou de rejet de notre promesse.

En TypeScript, nous pouvons fournir le type de données de la valeur renvoyée lorsque la promesse est remplie. Étant donné que l’erreur renvoyée par la promesse peut prendre n’importe quelle forme, le type de données par défaut de la valeur renvoyée lorsque la promesse est rejetée est défini sur any par le TypeScript.

Pour annoter le type de valeur de résolution de la promesse, nous utilisons une déclaration de type générique. Fondamentalement, vous promettez un type avec le constructeur Promise sous la forme de new Promise<Type>() qui indique le type de valeur résolue de la promesse. Mais vous pouvez également utiliser la syntaxe let p: Promise<Type> = new Promise() pour obtenir la même chose.

We Nous avons discuté des classes de génériques en détail dans la leçon sur les génériques.

(promesse.ts)

Dans l’exemple ci-dessus, findEven est une promesse créée à l’aide du constructeur Promise qui se résout après 1 seconde. Le type de données résolu de cette promesse est number, par conséquent, le compilateur TypeScript ne vous permettra pas d’appeler la fonction resolve avec une valeur autre qu’une valeur de type number number.

Le type par défaut de la valeur de rejet de la promesse est any, donc appeler la fonction reject avec n’importe quelle valeur est légal. C’est le comportement par défaut de TypeScript, et vous pouvez trouver le fil de discussion ici si vous avez vos propres opinions.

Puisque nous avons fourni le number comme type de données de résolution de promesse réussie, le compilateur TypeScript fournira le type number à l’argument de value argument du then div> méthode de rappel.

Le rappel fourni dans la méthode then est exécuté lorsque la promesse est résolue et le rappel fourni dans la méthode catch est exécuté lorsqu’il rejette ou une erreur lors de la résolution de la promesse. La méthode finally enregistre un rappel qui s’exécute lorsque la promesse est résolue ou rejetée.

Si le compilateur TypeScript se plaint de la méthode finally, cela signifie que votre compilateur TypeScript n’importe pas de définitions de type pour la méthode finally. Cette méthode a été introduite dans ES2016, elle est donc assez nouvelle. Les autres fonctionnalités de l’API Promise utilisées dans cette leçon sont assez nouvelles, assurez-vous donc que votre fichier tsconfig.json a toutes les nouvelles bibliothèques chargées.

(tsconfig.json)

Dans ma tsconfig.json, j’ai chargé la bibliothèque standard ES2020. Cela prend en charge toutes les fonctionnalités JavaScript jusqu’à ES2020. Si vous voulez en savoir plus sur le fichier tsconfig.json ou les bibliothèques standard, veuillez lire la leçon de compilation (à venir).

Chaînage de promesses

Les méthodes thencatch et finally renvoient implicitement une promesse. Toute valeur renvoyée par ces fonctions de rappel est enveloppée d’une promesse et renvoyée, y compris undefined. Cette promesse implicite est résolue par défaut, sauf si vous renvoyez délibérément une nouvelle promesse de ces méthodes qui pourrait échouer.

Par conséquent, vous pouvez ajouter des méthodes thencatch ou finally à l’une des méthodes précédentes thencatch ou finally méthode. Si une promesse implicite est renvoyée par l’une de ces méthodes, le type de valeur résolue de cette promesse implicite est le type de la valeur renvoyée. Voyons un exemple rapide.

(enchaînement de promesses.ts)

Nous avons modifié l’exemple précédent et ajouté une autre méthode then à la première méthode then. Comme la première méthode then renvoie une valeur de type string, la promesse implicite renvoyée par cette méthode sera résolue avec une valeur du type string. Par conséquent, la deuxième méthode then recevra un argument value de type string comme vous pouvez le voir sur les résultats.

Promesse.resolve

La méthode statique resolve de l’appel Promise renvoie une promesse déjà résolue avec succès avec une valeur que vous fournissez dans l’appel Promise.resolve(value). C’est plus facile que de créer une nouvelle instance de l’appel de promesse et d’ajouter une logique pour résoudre la promesse immédiatement.

(promise-resolve.ts)

Comme vous pouvez le voir dans les résultats ci-dessus, la promesse renvoyée par l’appel Promise.resolve(value) se résout toujours immédiatement avec une valeur number puisque le value l’argument a le type de number.

Promesse.reject

Similaire à la méthode statique Promise.resolve, la méthode Promise.reject(error) renvoie toujours une promesse rejetée. La valeur du rejet de promesse est extraite de l’argument error et son type est any.

(promise-reject.ts)

Le type de promesse retourné par la méthode Promise.reject est Promise<never> car cette promesse ne se résout jamais, il n’y aura donc aucune valeur de résolution de promesse. Par conséquent, le type de la valeur résolue par la promesse est never car never signifie la valeur qui ne se produit jamais.

Promesse.all

Dans certains scénarios, vous avez affaire à plusieurs promesses. Si vous souhaitez exécuter une fonction de rappel lorsque toutes les promesses sont résolues avec succès, utilisez la méthode statique Promise.all.

var pAll = Promise.all()pAll.then( ( ) => {___});

La méthode Promise.all prend un tableau (itérable précisément) de promesses et renvoie une nouvelle promesse. La promesse renvoyée pAll est résolue lorsque toutes les promesses p1, p2, ... sont résolues avec succès. Cette promesse est résolue avec une valeur de tableau qui contient les valeurs de résolution de promesse de p1, p2, ... dans l’ordre de leur apparition.

(promise-all.ts)

Comme vous pouvez le voir dans l’exemple ci-dessus, la méthode Promise.all est générique et prend le type la valeur résolue par chaque promesse qui lui est fournie. Fournir un type générique est très utile lorsque nous utilisons la valeur résolue de cette promesse collective, comme vous pouvez le voir dans le résultat ci-dessus.

Most La plupart des méthodes statiques de la classe Promise sont génériques comme le montrent les exemples ci-dessous.

Il y a une mise en garde avec Promise.all. Il implémente le mécanisme fail-fast, ce qui signifie que si l’une des promesses d’entrée p1, p2, ... est rejetée, pAll est rejetée. Si vous n’attendez pas que d’autres promesses en attente soient résolues.

(promise-all-reject.ts)

Comme vous pouvez le voir sur le résultat ci-dessus, comme la 3ème promesse a été rejetée juste après 1 seconde, la allPromise a été rejetée immédiatement.

Promesse.allSettled

La méthode statique Promise.allSettled est similaire à Promise.all mais contrairement à Promise.all, elle attend que toutes les promesses soient réglées (ce qui signifie jusqu’à ce qu’elles soient résolues ou rejetées). D’où la promesse renvoyée par Promise.allSettled ne sera jamais rejetée (mais nous avons de toute façon ajouté le bloc catch dans l’exemple ci-dessous).

(promesse-tout réglé.ts)

Travailler avec promise.allSettled peut être un peu écrasant que vous pouvez à partir du programme ci-dessus et de son résultat. Tout d’abord, la méthode allSettle renvoie une promesse qui se résout avec un tableau de valeurs PromiseSettledResult<type> lorsque toutes les promesses sont réglées. Le type est dérivé du type de la promesse d’entrée. Le type PromiseSettledResult ressemble à ci-dessous.

Ces types sont fournis par la bibliothèque standard de TypeScript. Ainsi, lorsqu’une promesse se résout, la méthode allSettled convertit sa valeur en forme PromiseFulfilledResult et lorsqu’elle échoue, elle la convertit en forme PromiseRejectedResult. C’est pourquoi lorsque allSettled est résolu, il s’agit d’un tableau d’objets dans lequel chaque objet a une forme d’interface PromiseFulfilledResult ou PromiseRejectedResult.

Puisque PromiseFulfilledResult est une union de PromiseFulfilledResult et PromiseRejectedResult qui a une propriété commune status de type de données littérales, nous pouvons l’utiliser comme discriminant dans le switch/case garde.

We Nous avons parlé de switch/casegarde de type et syndicats discriminants dans la leçon de système de type.

(promesse-tout-réglé.ts)

Promesse.race

Le Promise.race prend un tableau (itérable précisément) de promesses et renvoie une nouvelle promesse qui se résout ou se rejette dès que l’une des promesses d’entrée se résout ou se rejette. En d’autres termes, la promesse renvoyée par Promise.race est réglée avec le résultat d’une des promesses d’entrée qui se règle rapidement.

(promise-race.ts)

Contrairement à Promise.all ou Promise.allSettled, cette méthode ne renvoie qu’une seule valeur de la première promesse réglée, d’où le type de la promesse retournée est Promise<number> dans le cas ci-dessus. Comme la 1ère promesse s’est réglée en premier parmi d’autres, le rappel then du fastestPromise est appelé après 500 ms avec la valeur de la promesse résolue.

💡 La nouvelle méthode Promise.any() a atteint l’étape 4 de la piste de proposition ECMAScript. Promise.any ressemble beaucoup à Promise.race mais il attend que la première promesse soit résolue. Cette méthode génère une exception AggregateError si toutes les promesses sont rejetées.