JavaScript Async/Await: Zero To Hero Plus Cheat Sheet

JavaScript Async/Await: Zero To Hero Plus Cheat Sheet

Donc, vous venez de finir de tout apprendre sur les promesses JavaScript et vous allez vous mêler à l’élite du développement Web de votre équipe lorsque quelqu’un vous dit: « Utilisez-vous async / wait aussi? »

Euh oh. Vous jouez cool et revenez sur votre ordinateur portable pour lire cet article. Bon mouvement.

Heureusement pour vous, si vous comprenez les promesses, vous avez déjà 80% du chemin pour comprendre async / wait. Si vous ne le faites pas, jetez un coup d’œil à mon article sur les promesses JavaScript pour un récapitulatif détaillé ainsi qu’un aide-mémoire ici avant de continuer!

Sans plus tarder, passons à l’async / wait!

async / wait est une fonctionnalité de JavaScript qui vous permet d’écrire du code asynchrone qui ressemble beaucoup à du code synchrone, et qui fonctionne correctement sous JavaScript.

Voici un exemple:

Celles-ci seraient appelées fonctions asynchrones. Il y a quelques caractéristiques syntaxiques à noter:

async est ajouté au début de la définition de la fonction
Rien de spécial n’est fait pour la valeur de retour
Les fonctions asynchrones peuvent utiliser d’autres fonctions asynchrones
Pour obtenir le résultat d’une autre fonction asynchrone, utilisez le mot-clé wait – vous ne pouvez utiliser wait que dans une fonction async!
Vous pouvez voir que getUserFullName se lit très bien comme une fonction JavaScript classique (synchrone) – il agit comme ça aussi! En utilisant wait, le thread JavaScript s’arrête et attend le résultat de getFirstName avant de passer à la ligne suivante, puis s’arrête et attend à nouveau le résultat de getLastName avant de passer à la ligne suivante.

Voici un autre exemple pour illustrer davantage le comportement de blocage async / wait:

Dans cet exemple de média social, nous obtenons l’activité de la dernière publication d’un utilisateur donné. Cette fonction fonctionnera à peu près comme elle se lit:

Attendez que tous les messages soient récupérés
Une fois terminé, obtenez le premier (disons le tri par le plus récent)
Attendez que tous les commentaires soient récupérés
Attendez que tous les goûts soient récupérés
Renvoyer une valeur
Cette lisibilité est l’une des raisons pour lesquelles un développeur peut préférer async / attendre aux promesses brutes!

Comme indiqué au début, async / wait est construit sur des promesses JavaScript. En ajoutant asynchrone à la définition de la fonction, même si aucune promesse n’est explicitement retournée, elle est convertie en une fonction qui renvoie une promesse sous le capot. Cela est accompli par les transformations suivantes:

Le corps de la fonction asynchrone devient le corps de la fonction de résolution d’une promesse
Le résultat final renvoyé dans la fonction asynchrone est appelé avec resol ()
Tous les appels en attente vers d’autres fonctions asynchrones sont également convertis intelligemment en promesses – tout code venant après un appel en attente se termine dans un bloc .then (), ce qui oblige le code qui le suit à attendre jusqu’à ce qu’il soit terminé!
L’exemple de la fonction asynchrone getLatestPostActivity donné ci-dessus est approximativement traduit comme suit en utilisant Promises sous le capot:

Vous pouvez voir qu’une nouvelle fonction est créée qui retourne une promesse, le corps de la fonction asynchrone se termine dans l’exécuteur de la promesse et chaque appel en attente à l’intérieur est structuré de manière à se dérouler les uns après les autres. Enfin, à la fin, le retour de la fonction async originale est passé dans la résolution de cette promesse traduite!

Besoin d’une preuve qu’une fonction asynchrone retourne une promesse? Très bien mon ami sceptique – voici un Codepen qui le démontre:

Une chose à noter est que l’argument qui suit attend dans la fonction asynchrone doit renvoyer une promesse! Cela signifie que vous pouvez également utiliser wait avec raw Promises:

Jusqu’ici, nous avons discuté asynchrone / wait en supposant qu’aucune erreur ne se produise – dans la terminologie Promise, nous n’avons discuté que de ce qui se passe lorsque resol () est appelé. Mais comment rejette-t-il dans cette situation?

La fonction asynchrone utilise une erreur en jetant et en essayant / attrapant des blocs pour émuler et gérer les appels de rejet ()! Voici un exemple:

C’est à peu près tout ce qu’il ya à faire. Comme on peut s’y attendre dans le code JavaScript synchrone normal, s’il y a plusieurs appels en attente, s’il y a une exception, le reste du code ne sera pas exécuté et le code passera immédiatement au bloc catch.

Lorsque vous encapsulez votre fonction asynchrone dans un bloc try / catch, n’oubliez pas de continuer à utiliser wait!

Il y a un inconvénient majeur avec async / wait qui est facile à manquer et difficile à déboguer si vous n’êtes pas au courant. async / wait joue bien avec les boucles for, for: of et while. Voici la syntaxe pour chacune de ces boucles:

async / wait ne joue pas bien avec les boucles .forEach () cependant. Les boucles .forEach () ne sont pas compatibles avec Promise et si vous essayez d’attendre une promesse à l’intérieur d’une boucle .forEach (), elle continuera de fonctionner au lieu d’attendre chaque itération comme vous le souhaiteriez. Voici un Codepen démontrant ce comportement:

Comme vous pouvez le constater, les “avant” et “après” se terminent d’abord, suivis de toutes les fonctions asynchrones en même temps, ce qui n’est pas ce que vous allez probablement faire ici.

Si vous essayez d’utiliser une boucle .forEach () avec async / wait, il est probable que vous essayez de lancer des requêtes une par une au lieu de toutes en même temps. Pour ce faire, je vous recommande d’utiliser une boucle for: of comme décrit ci-dessus.

Si

vous souhaitez lancer un ensemble de requêtes asynchrones et les attendre toutes, ce qui est traité dans la section suivante!

Revenons sur notre exemple de média social:

C’est un excellent tout, mais si vous remarquez, une fois que nous récupérons l’objet post, nous récupérons les commentaires, attendons, puis récupérons les likes. Mais nous n’avons pas vraiment besoin d’attendre la fin de la demande de commentaires pour aller chercher les « J’aime ». Nous savons comment faire cela en utilisant des promesses brutes, mais comment pouvons-nous accomplir cela avec async / wait?

Tu te souviens de notre vieil ami Promise.all ()? C’est bien de retour pour nous aider ici aussi, avec seulement une légère différence de syntaxe!

Ici, nous avons directement passé les deux fonctions asynchrones que nous voulons attendre dans Promise.all (). Si au lieu de cela vous avez une liste de demandes asynchrones que vous souhaitez effectuer, vous pouvez utiliser une stratégie similaire:

Comme nous savons déjà que nous pouvons attendre une promesse et que Promise.all () renvoie une promesse résolue une fois la liste résolue, tous les commentaires contiennent une liste d’objets «commentaires» une fois toutes les promesses terminées.

Parfois, vous souhaiterez peut-être utiliser async / wait dans un contexte où vous n’êtes pas dans une fonction async. C’est un peu gênant mais vous pouvez le faire à condition d’être pleinement conscient de son fonctionnement. Cela ressemblera à quelque chose comme ça:

Puisque wait ne peut être utilisé que dans une fonction asynchrone, vous devez donc (légèrement maladroitement) envelopper votre fonction dans une fonction nommée ou anonyme, puis l’appeler.

Il est important de noter que puisque vous initialisez une fonction asynchrone dans un code synchrone, le code environnant continue à être exécuté. Donc, la sortie de ce code serait « avant », « après », « premier », « deuxième », « troisième ».

Essayer de convertir du code Promise en fonctions asynchrones peut s’avérer un excellent moyen de s’exercer à utiliser async / wait. Passons maintenant à la conversion de ce qui suit pour utiliser async / wait:

Dans cet exemple, pour un utilisateur, nous allons chercher leurs suiveurs, le meilleur suiveur et voir combien de messages ils ont. Nous identifions également les erreurs et imprimons sur la console une fois que tout est terminé.

Pour convertir cette fonction en une fonction asynchrone, rassemblons tout ce que nous avons couvert dans cet article!

Nous n’avons pas besoin de spécifier l’objet Promise – la fonction exécuteur devient le corps de la fonction asynchrone
Remplacer tous les blocs .then () par wait
Utilisez un try / catch à la place du bloc .catch ()
retourne la valeur qui était passée dans resol ()
Déplacez le code de bloc .finally () pour qu’il se trouve juste avant le retour
Avec tous ces changements, nous nous retrouvons avec ce qui suit:

Rappelez-vous qu’en ce qui concerne try / catch, en raison de la portée, vous ne pouvez pas définir votre variable dans le bloc try et essayer de l’utiliser après le test / catch. Donc, n’oubliez pas d’utiliser let comme dans cet exemple!

Les fonctions asynchrones sont très lisibles par rapport à Promises en ce qui concerne les chaînes, en particulier dans les scénarios dans lesquels vous devez utiliser les résultats d’une ou deux requêtes dans une troisième, par exemple. Il est également très simple de lancer une attente Promise.all (…) lorsque vous devez activer des fonctions asynchrones simultanées.

Cependant, n’ayez pas peur de mélanger et d’assortir Promesses et async / wait! Si, dans votre cas d’utilisation particulier, vous trouvez qu’il est plus lisible ou plus facile d’utiliser Promises, c’est acceptable. Je leur donnerais une chance de les convertir, mais si cela n’a aucun sens dans votre contexte spécifique, pas de problème!

De plus, lors de l’utilisation de fonctions asynchrones, n’oubliez pas les meilleures pratiques applicables au développement de logiciels en général! Gardez vos fonctions aussi petites que possible et avec un objectif clair.

Heureux, et rappelez-vous – les bonnes choses vont à ceux qui attendent!

Utilisation de PromisesAsync / Await lors de la gestion des erreurs Async / AwaitAsync / Await à l’aide de: LoopAsync / Await pendant que LoopAsync / Await est inséré dans du code synchrone

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *