Bonjour ! Prêt à simplifier votre code asynchrone ?
Introduction
Dans la leçon précédente, nous avons exploré les Promises, l'outil fondamental pour gérer les opérations asynchrones en JavaScript. Vous avez appris à les créer, à les chaîner avec .then(), et à gérer les erreurs avec .catch(). Vous avez vu que bien que puissantes, les chaînes de Promises peuvent parfois devenir complexes, surtout lorsque la logique métier s'alourdit.
Aujourd'hui, nous allons découvrir une syntaxe qui révolutionne l'écriture du code asynchrone : async/await. L'objectif est simple : vous permettre d'écrire du code asynchrone qui a l'apparence et la lisibilité du code synchrone. Pour vous qui venez d'un environnement comme Laravel/PHP où le code s'exécute souvent de manière séquentielle, async/await sera une manière très naturelle et intuitive de gérer l'asynchronisme de Node.js.
Il est crucial de comprendre que async/await n'est pas un nouveau concept, mais du "sucre syntaxique" au-dessus des Promises. Tout ce que vous avez appris sur les Promises reste valable ; async/await est simplement une meilleure façon de les utiliser.
À la fin de cette leçon, vous saurez transformer du code basé sur .then/.catch en code async/await clair, concis et facile à maintenir.
1. async/await : Une meilleure syntaxe pour les Promises
La meilleure façon de comprendre async/await est de le voir en action et de le comparer directement au code que vous connaissez déjà.
La vidéo suivante fait un excellent travail en montrant comment refactoriser une fonction qui utilise des Promises avec .then() et .catch() vers la nouvelle syntaxe async/await.
Cette vidéo, de la chaîne Web Dev Simplified, compare le code basé sur les Promises à celui utilisant async/await. Elle est parfaite pour visualiser la simplification que cette syntaxe apporte.
Regardez la vidéo jusqu'à 06:24. Concentrez-vous sur les points suivants : La structure du code initial avec .then() et .catch() (jusqu'à 02:35). La transformation de ce code en une fonction async utilisant await (à partir de 03:11). La manière de gérer les erreurs avec un bloc try...catch, qui remplace le .catch() des Promises (à partir de 05:23).
Comme vous l'avez vu, le code devient beaucoup plus linéaire et facile à lire. Finies les fonctions imbriquées et les chaînes de .then().
2. Les deux mots-clés : async et await
Pour bien maîtriser cette syntaxe, il faut comprendre le rôle de chaque mot-clé. L'article suivant, du tutoriel de javascript.info, est une référence incontournable qui décompose parfaitement ces concepts.
Async/await - The Modern JavaScript Tutorial
Nous allons maintenant lire les sections clés de l'article 'Async/await' pour formaliser ce que vous avez vu dans la vidéo.
Lisez les sections suivantes : 'Async functions' : Comprenez la règle simple : une fonction async retourne toujours une Promise. 'Await' : Saisissez comment await met en pause l'exécution de la fonction uniquement, en attendant que la Promise se résolve, sans bloquer le reste de l'application. 'Error handling' : Voyez comment les rejets de Promises sont transformés en exceptions, que l'on peut attraper avec un try...catch standard.
Synthèse des règles
Voici un résumé des règles d'or de async/await :
-
Le mot-clé
async:- Il se place avant la déclaration d'une fonction (
async function myFunction() { ... }). - Il a deux effets principaux :
- Il garantit que la fonction retournera toujours une Promise. Si vous retournez une valeur simple (ex:
return 5), elle sera automatiquement "enveloppée" dans une Promise résolue (Promise.resolve(5)). - Il autorise l'utilisation du mot-clé
awaità l'intérieur de cette fonction.
- Il garantit que la fonction retournera toujours une Promise. Si vous retournez une valeur simple (ex:
- Il se place avant la déclaration d'une fonction (
-
Le mot-clé
await:- Il ne peut être utilisé que à l'intérieur d'une fonction
async. - Il se place devant une expression qui retourne une Promise (ex:
await fetch('/api/data')). - Il met en pause l'exécution de la fonction
asyncjusqu'à ce que la Promise soit réglée (settled).- Si la Promise est tenue (
fulfilled),awaitretourne la valeur de résolution. - Si la Promise est rejetée (
rejected),await"jette" (throws) l'erreur de rejet.
- Si la Promise est tenue (
- Il ne peut être utilisé que à l'intérieur d'une fonction
-
Gestion des erreurs avec
try...catch:- Puisque
awaitjette une exception quand une Promise est rejetée, nous pouvons utiliser le bloctry...catchque vous connaissez peut-être déjà d'autres langages. - On place le code "à risque" (les appels avec
await) dans le bloctry. - On attrape les éventuelles erreurs dans le bloc
catch(err). C'est une méthode de gestion d'erreurs centralisée et beaucoup plus lisible que de chaîner des.catch().
- Puisque
3. Exemple pratique : Avant et Après
Mettons tout cela en pratique avec un scénario courant : récupérer des données depuis une API.

Imaginons que nous voulons récupérer un utilisateur, puis, en fonction de son ID, récupérer ses articles de blog.
Version avec .then/.catch (ce que vous avez appris avant) :
function fetchUserAndPosts() {
fetch('https://api.example.com/users/1')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json(); // Retourne une Promise
})
.then(user => {
console.log(`User found: ${user.name}`);
// Maintenant, on fetch les posts avec l'ID de l'utilisateur
return fetch(`https://api.example.com/users/${user.id}/posts`);
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(posts => {
console.log(`Found ${posts.length} posts.`);
})
.catch(error => {
console.error("An error occurred:", error.message);
});
}
fetchUserAndPosts();
Ce code fonctionne, mais il nécessite plusieurs .then() imbriqués ou chaînés, et la gestion d'erreur peut devenir complexe.
Version avec async/await (la manière moderne) :
async function fetchUserAndPostsAsync() {
try {
// Étape 1: Récupérer l'utilisateur
const userResponse = await fetch('https://api.example.com/users/1');
if (!userResponse.ok) {
throw new Error(`HTTP error! status: ${userResponse.status}`);
}
const user = await userResponse.json();
console.log(`User found: ${user.name}`);
// Étape 2: Récupérer les posts
const postsResponse = await fetch(`https://api.example.com/users/${user.id}/posts`);
if (!postsResponse.ok) {
throw new Error(`HTTP error! status: ${postsResponse.status}`);
}
const posts = await postsResponse.json();
console.log(`Found ${posts.length} posts.`);
} catch (error) {
// Un seul endroit pour gérer toutes les erreurs (réseau, JSON, etc.)
console.error("An error occurred:", error.message);
}
}
fetchUserAndPostsAsync();
La différence est frappante. La version async/await se lit comme une série d'instructions synchrones. La logique métier est claire et non noyée dans la syntaxe de gestion de l'asynchronisme.
4. async/await et la Boucle d'Événements
Une question importante : async/await change-t-il le fonctionnement de la boucle d'événements ? La réponse est non.
Le mot-clé await ne "bloque" pas magiquement JavaScript. Quand le moteur JavaScript rencontre un await, il suspend l'exécution de la fonction async actuelle, et rend la main à la boucle d'événements. La boucle peut alors continuer à traiter d'autres tâches (autres événements, rendus UI, etc.). Une fois que la Promise attendue est résolue, la boucle d'événements planifie la reprise de l'exécution de la fonction async là où elle s'était arrêtée.

async/await est donc une abstraction qui nous permet de ne pas penser aux .then() tout en respectant le modèle non-bloquant de Node.js.
Conclusion
Vous venez de faire un grand pas vers l'écriture de code Node.js moderne, propre et maintenable.
Points clés à retenir :
async/awaitest une syntaxe qui simplifie l'utilisation des Promises, rendant le code asynchrone aussi lisible que du code synchrone.- Une fonction déclarée avec
asyncretourne toujours une Promise. - Le mot-clé
awaitmet en pause l'exécution d'une fonctionasyncjusqu'à ce qu'une Promise soit résolue, sans bloquer le thread principal. - La gestion des erreurs se fait élégamment avec les blocs
try...catch, une structure standard et familière. async/awaitne change rien au fonctionnement de la boucle d'événements ; il s'intègre parfaitement dans le modèle asynchrone de JavaScript.
Dans notre prochaine leçon, nous aborderons un autre pilier de la structuration de code en Node.js : les modules ES (import/export). Cela vous permettra d'organiser votre code en fichiers séparés et réutilisables, une compétence essentielle pour construire des applications backend scalables.