- Async/await s'appuie sur les promesses pour offrir un code asynchrone plus lisible, plus proche du style synchrone traditionnel.
- Les fonctions asynchrones renvoient toujours une promesse et vous permettent d'utiliser await pour suspendre leur exécution sans bloquer le thread principal.
- La gestion des erreurs avec try/catch et des utilitaires comme Promise.all facilite le contrôle des échecs et la combinaison de plusieurs opérations en parallèle.
- L'utilisation combinée des promesses, d'async/await et d'API comme fetch constitue le fondement du développement JavaScript moderne orienté réseau.

La programmation asynchrone en JavaScript est devenu indispensable dans le développement web moderne : requêtes API, accès à bases de donnéesLa lecture de fichiers ou toute opération prenant plus d'un instant en dépend pour assurer le bon fonctionnement de l'interface. Grâce à cela, promesses, async/await et les API Nous disposons d'un ensemble d'outils très performants pour contrôler ce flux sans bloquer l'application.
Pendant des années, ce modèle a été principalement utilisé rappels et promesses enchaînéesqui, bien qu'elles fonctionnent très bien, peuvent aboutir au fameux « enfer des rappels » ou à des chaînes interminables de .then() y .catch() difficile à suivre. Avec l'arrivée de async/await dans ECMAScript 2017JavaScript a fait un bond en avant considérable en matière de lisibilité, permettant d'écrire du code asynchrone dans un style presque identique à celui du code synchrone traditionnel.
Qu’est-ce que la programmation asynchrone en JavaScript et pourquoi est-elle si importante ?
La programmation asynchrone Il s'agit d'une méthode d'organisation du code permettant à une tâche de démarrer et au programme de poursuivre son exécution sans se bloquer en attente d'une réponse. En JavaScript, c'est essentiel car le langage s'exécute, dans le navigateur et dans Node.js, sur un cluster. fil principal unique qui prend en compte à la fois la logique et l'interface.
Quand vous lancez un Requête HTTP vers une APILorsqu'on lit un fichier ou qu'on interroge une base de données, ces opérations peuvent prendre de quelques millisecondes à plusieurs secondes. Si elles étaient synchrones, l'utilisateur verrait la page bloquée et ne pourrait pas interagir. Avec le modèle asynchrone, le moteur JavaScript délègue ces tâches et peut continuer à fonctionner pendant ce temps. Affichage de l'interface utilisateur, gestion des événements et exécution d'autres scripts.
À l'origine, le mécanisme standard de réaction à la fin d'une opération consistait à transmettre un fonction de rappel comme argument. Cette fonction a ensuite été exécutée avec le résultat ou l'erreur. Le problème est que, en enchaînant les rappels dans d'autres rappels, on obtient le redoutable l'enfer des rappels: Code avec une indentation excessive, difficile à lire, à déboguer et à maintenir.
Pour tenter de résoudre une partie de ce chaos, les mesures suivantes ont été prises : prometqui encapsulent le résultat d'une opération asynchrone et permettent d'enchaîner les actions avec .then() et gérer les échecs avec .catch()C'était déjà une grande amélioration, mais le code restait encore truffé de fonctions de rappel « déguisées » derrière ces méthodes.
Les promesses : le fondement de l'async/await
Avant de comprendre async/await, il est essentiel de bien comprendre ce qu'est un promesses en JavaScriptUne promesse est un objet qui représente le résultat futur d'une opération asynchrone : quelque chose qui ne s'est pas encore produit mais qui se produira plus tard, avec succès ou sans succès.
Une promesse standard peut se trouver dans l'un des trois états bien définis suivants : en attente (En attente) pendant que l'opération est en cours, terminée (rempli) lorsqu'elle se termine bien et produit de la valeur, ou lorsqu'elle est rejetée (rejeté) lorsqu'il échoue et génère une erreur. état de la promesse détermine quelles fonctions de rappel seront exécutées ensuite.
Lorsque vous créez une promesse en utilisant constructeur PromiseVous lui transmettez une fonction exécutable qui reçoit deux arguments : resolve y rejectSi l'opération se déroule bien, vous appelez resolve(valor)En cas de problème, vous invoquez reject(error)Ensuite, de l'extérieur, vous pouvez utiliser miPromesa.then() pour traiter le résultat et .catch() pour gérer les erreurs.
Outre les promesses élaborées manuellement, de nombreuses API de langages modernes le font déjà Ils tiennent une promesse faite dans le cadre de cette série.. La fonction fetch()Par exemple, elle initie une requête HTTP et renvoie immédiatement une promesse qui sera finalement résolue avec un objet. Response ou rejetée en cas de panne de réseau.
Pour gérer plusieurs tâches en parallèle, JavaScript offre des utilitaires tels que : Promise.all()Cette méthode prend un tableau de promesses et renvoie une nouvelle promesse qui ne se résout que lorsque toutes les promesses ont été tenues, ou est rejetée si l'une d'entre elles échoue. Ceci est particulièrement utile lorsque vous souhaitez combiner des données provenant de différentes sources avant de continuer.
Concepts clés : async, await et le modèle d’erreur
La syntaxe de async/await est basé sur les promesses.Cela ne les remplace pas. Cela offre une manière plus pratique et plus claire, plus proche de la programmation synchrone, de travailler avec eux, réduisant ainsi le bruit visuel de .then() enchaîné.
Le mot clé async Il est placé avant une fonction pour indiquer au moteur JavaScript que la fonction fonctionnera de manière asynchrone et que, quoi qu'il arrive à l'intérieur, tiendra toujours sa promesseMême si vous renvoyez une valeur normale, le moteur l'encapsulera automatiquement dans Promise.resolve(valor).
Pour sa part, le mot réservé await ne peut être utilisé que dans une fonction déclarée comme asyncSa fonction est de suspendre l'exécution au sein de cette fonction jusqu'à ce que la promesse qui lui est transmise soit tenue. qu'il soit résolu ou rejeté, en renvoyant directement la valeur résolue ou en levant une exception si la promesse se termine par une erreur.
Lorsque vous utilisez await promesa et la promesse est résolue, vous obtenez le résultat comme s'il s'agissait d'un appel synchrone. Si, en revanche, la promesse est rejetée, Une exception est générée à ce moment-là., équivalent à faire un throw errorCela permet de réutiliser les mêmes structures de gestion des erreurs que dans le code synchrone, telles que : try..catch.
En encapsulant nos appels asynchrones dans un bloc try { ... } catch (error) { ... }Nous pouvons détecter les cas où l'une des promesses échoue, afficher des messages appropriés à l'utilisateur ou prendre des décisions telles que réessayer, rediriger ou consigner l'échec dans un système externe.
Le mot-clé async : fonctions qui renvoient toujours des promesses
Lieu async devant une fonction Cela a deux conséquences très importantes : d’une part, cela oblige à ce que la valeur de retour soit toujours une promesse ; d’autre part, cela permet l’utilisation de await au sein même de cette fonction, ce qui modifie complètement la structure du flux asynchrone.
Si vous déclarez quelque chose comme async function sumar() { return 1; }Bien que cela puisse paraître une fonction normale, ce que vous obtenez en réalité est un fonction qui renvoie une promesse précédemment résolue avec le courage 1En dehors de votre système, vous devrez accéder à ce résultat en utilisant await sumar() ou avec sumar().then() si vous préférez le style à chaînes.
Vous pouvez également renvoyer explicitement une promesse depuis une fonction. async, par exemple return Promise.resolve(1);et le comportement sera identique. Dans les deux cas, la fonction est conforme au modèle des promesses, ce qui facilite son intégration avec d'autres fonctions et utilitaires asynchrones tels que : Promise.all().
Il est très fréquent, lorsque nous débutons, d'oublier de marquer une fonction comme telle. async et pourtant nous utilisons await dansDans ce cas, JavaScript générera une erreur de syntaxe indiquant que await Ceci n'est valable que pour les fonctions asynchrones (ou les modules qui les prennent en charge à un niveau supérieur). Ce message vous rappelle que async y await ils vont toujours de pair.
Dans les environnements où nous n'utilisons pas de modules ou n'avons pas à prendre en charge les anciens navigateurs, il existe un modèle répandu qui consiste en Enveloppez le code dans une fonction asynchrone auto-exécutable, quelque chose comme (async () => { ... })();De cette manière, le bloc entier reste dans un contexte asynchrone sans «contaminer» l'espace global.
Comment fonctionne la fonction await et que fait-elle concrètement avec les promesses ?
Le véritable changement de mentalité survient avec awaitLorsque le moteur JavaScript rencontre const resultado = await algunaPromesa; au sein d'une fonction async, interrompre l'exécution de cette fonction à ce moment-là. et retourne à la boucle d'événements pour continuer à s'occuper d'autres tâches.
Pendant ce temps, la promesse suit son cours indépendamment. Lorsqu'elle est finalement résolue, le moteur reprend l'exécution de la fonction juste après la ligne contenant await, en affectant à la variable la valeur renvoyée par la promesseDu point de vue de quelqu'un qui lit le code, cela ressemble à un appel synchrone qui prend simplement un peu plus de temps.
Ce qui est intéressant, c'est que cette pause Il ne bloque pas le processeurLe thread JavaScript principal peut traiter les événements utilisateur, les animations, le code asynchrone, etc. C'est pourquoi nous disons que await C'est plutôt un abstraction syntaxique élégante à propos des promesses d'une nouvelle façon d'exécuter des tâches en arrière-plan.
Si vous préférez, vous pouvez imaginer que la combinaison const resultado = await promesa; es promesa.then(valor => { resultado = valor; ... }) ou quelque chose d'équivalent, mais distribué de manière linéaire, ce qui évite les rappels imbriqués et améliore la clarté du flux.
Un détail curieux : si vous déménagez à await un objet qui n'est pas une promesse mais qui possède une méthode .then()Le moteur tentera de le traiter comme si c'était le cas. Il invoquera cela .then() avec deux fonctions internes de résolution et rejet très semblables à celles du constructeur de Promise. De cette manière, await Il est compatible avec les implémentations de promesses de type « thenable ».
Gestion des erreurs avec async/await : try/catch et promesses rejetées
Quand une promesse est rejeter pendant que vous utilisez awaitL'effet direct est qu'une exception est levée sur cette ligne. Du point de vue de votre code, c'est comme si vous aviez écrit throw error; juste là où le await, ce qui provoque le passage de l'exécution au bloc catch plus près.
Par exemple, si vous utilisez const datos = await obtenerDatos(); et la fonction obtenerDatos Elle renvoie une promesse qui se termine par une erreur ; le flux passera directement à la suite bloque catch (error) votre try..catchSi vous n'avez pas de bloc de capture autour, la promesse implicite que la fonction renvoie async Elle sera rejetée.
Cela signifie que, même s'il peut encore y avoir des promesses à l'intérieur, lorsque vous travaillez avec async/await est la manière naturelle de gérer les erreurs c'est avec try..catchComme pour tout autre code JavaScript générant des exceptions, cette unification des styles simplifie considérablement la logique et réduit la nécessité de mémoriser différents modèles selon que le code est synchrone ou asynchrone.
Si, par erreur, vous oubliez d'ajouter un .catch() à la promesse renvoyée par une fonction async En cas d'échec, l'environnement affichera un avertissement. « promesse non gérée » (promesse non géréeDe plus, vous pouvez utiliser l'événement global dans le navigateur. unhandledrejection enregistrer un gestionnaire qui capture toutes ces erreurs et empêche qu'elles ne passent inaperçues.
Quand tu combine await avec des utilitaires tels que Promise.all, une simple erreur dans l'une des promesses propage la promesse commune et aboutit finalement à une exception que vous pouvez intercepter avec try..catchDe cette manière, la gestion des erreurs dans les flux de travail complexes reste cohérente et centralisée.
Async/await avec fetch : appels d’API étape par étape
L'une des utilisations les plus courantes d'async/await est l'accès à API HTTP utilisant la fonction fetch()Cette API renvoie une promesse qui se résout en un objet. Response, sur laquelle vous pouvez ensuite invoquer des méthodes telles que .json() o .text()qui, à leur tour, font de nouvelles promesses.
Imaginez que vous souhaitiez encapsuler la logique de requête de données à partir d'un point de terminaison dans une fonction. Si vous déclarez async function obtenerDatos(), à l'intérieur vous pouvez attendre la réponse du réseau avec await fetch(...) puis transformer le corps en JSON avec const datos = await respuesta.json(); sans avoir besoin d'enchaîner plusieurs .then().
Pour s'assurer que le serveur a répondu correctement, il est courant de vérifier la propriété respuesta.okqui indique si le code d'état HTTP se situe dans la plage 200-299. Sinon, vous pouvez générer manuellement une erreur avec throw new Error('Error en la red');, ce qui entraînera catch Saisir la situation.
Organisez l'ensemble du flux dans un try { ... } catch (error) { ... } Cela rend la fonction asynchrone beaucoup plus résiliente : tout problème, qu’il soit lié au réseau, à l’analyse JSON ou à la logique, déclenchera le bloc de capture où vous pourrez… consigner l'erreur ou afficher un message plus convivial.
Finalement, pour utiliser cette fonction, il suffit de l'appeler comme n'importe quelle autre : obtenerDatos();N'oubliez pas que, étant asynchrone, elle renvoie une promesse ; vous devrez donc choisir, de l'extérieur, si vous souhaitez l'utiliser. await obtenerDatos() au sein d'une autre fonction async ou le gérer avec .then().catch() si vous vous trouvez dans un contexte non asynchrone.
Exécutez plusieurs opérations en parallèle avec Promise.all et async/await
Souvent, vous ne souhaitez pas attendre la fin d'une requête avant de lancer la suivante ; vous vous intéressez plutôt à… lancer plusieurs opérations asynchrones simultanément et continuer une fois qu'ils auront tous terminé. Pour cela, la méthode Promise.all() s'adapte parfaitement.
Supposons que vous ayez besoin d'utiliser deux API différentes, par exemple /datos1 y /datos2, et après fusionner les informations en un seul objetAu lieu d'attendre que la première soit terminée avant de commencer la seconde, vous pouvez écrire quelque chose comme const [r1, r2] = await Promise.all([fetch(url1), fetch(url2)]); et les deux demandes seront déposées en parallèle.
Une fois que vous avez les deux réponses, vous pouvez postuler await pour chacun d'eux, afin de les transformer en JSON : const d1 = await r1.json(); const d2 = await r2.json();Enfin, c'est très courant combiner les données avec l'opérateur de propagation : const datosCombinados = { ...d1, ...d2 };, ce qui crée une structure unique qui combine les propriétés des deux.
Ce bloc entier devrait être enveloppé dans un try..catchcar toute défaillance dans l'une des requêtes entraînera Promise.all() est rejetée. Grâce à async/await, il est possible de gérer ce type de scénarios avec opérations simultanées Visuellement simple, il est pourtant très performant.
Ce modèle est particulièrement utile lorsque votre application web nécessite plusieurs ressources indépendantes avant qu'une vue puisse être affichée : par exemple, en obtenant simultanément la configuration, les données utilisateur et les statistiques d'utilisation, réduisant ainsi le temps d'attente global.
Avantages réels de l'async/await par rapport aux promesses et aux rappels « purs »
Utilisation de async/await offre un certain nombre d'avantages pratiques Ces avantages sont perceptibles dès les premiers exemples et jusqu'aux applications à grande échelle. Le plus évident est la lisibilité : le flux est écrit de haut en bas sans avoir recours à des fonctions imbriquées ou chaînées. .then() l'un après l'autre.
Un autre point fort est le maintenabilité du codeGrâce à une structure plus linéaire, il est plus facile d'apporter des modifications, d'extraire des parties dans des fonctions auxiliaires ou de réutiliser la logique. Cela se traduit directement par moins d'erreurs et une prise en main plus aisée pour les nouveaux utilisateurs du projet.
Gestion des erreurs avec try..catch au lieu de plusieurs .catch() éparpillé Cela permet de centraliser la logique de gestion des pannes. Vous pouvez en entourer plusieurs await avec un seul bloc et mettre en œuvre une politique de gestion des erreurs cohérente, sans perdre de vue la ligne sur laquelle le problème est survenu.
Du point de vue des performances, async/await ne rend pas le code plus rapide en soi, mais peut vous inciter à utiliser des modèles comme Promise.all() pour exécuter des tâches en parallèle là où vous les auriez auparavant exécutées en série. Le résultat est temps d'attente total réduit pour l'utilisateur final.
De plus, async/await est compatible avec les promesses traditionnellesVous n'avez pas besoin de réécrire tout votre code pour l'adopter. Vous pouvez combiner les fonctions qui l'utilisent. .then() avec d'autres qui utilisent await Aucun problème, ce qui facilite la migration progressive des projets.
Dans l'écosystème moderne, tant dans les navigateurs que dans Node.js, la plupart des outils et des bibliothèques reposent déjà sur les promesses et l'async/await. Il est donc essentiel de bien maîtriser ces concepts. une condition nécessaire pour travailler avec JavaScript moderne dans le cadre de projets professionnels.
Tout cet ensemble d'idées — promesses, async/await, fetch, Promise.allLe guide d'essai/de correction et le glossaire des termes clés constituent un cadre très solide pour l'écriture. code asynchrone clair, lisible et robusteLeur maîtrise vous permet de créer des applications web modernes qui répondent rapidement, tirent pleinement parti du réseau et sont beaucoup plus faciles à maintenir dans le temps.
Écrivain passionné par le monde des octets et de la technologie en général. J'aime partager mes connaissances à travers l'écriture, et c'est ce que je vais faire dans ce blog, vous montrer toutes les choses les plus intéressantes sur les gadgets, les logiciels, le matériel, les tendances technologiques et plus encore. Mon objectif est de vous aider à naviguer dans le monde numérique de manière simple et divertissante.