Pourquoi Async/Await en JavaScript ?
Async/Await est une syntaxe moderne qui permet d'écrire des fonctions asynchrones de manière plus lisible et intuitive, tout en conservant les avantages des promesses. En effet, elle simplifie la gestion des opérations asynchrones comme les appels API, la lecture de fichiers, les tâches parallèles, etc.
Un cas d'usage concret est l'appel à une API pour récupérer des données et les afficher sur une interface utilisateur. Sans Async/Await, on aurait besoin de chaîner plusieurs callbacks imbriqués, ce qui rend le code difficile à lire et à maintenir. Avec Async/Await, l'opération peut être écrite comme si elle était synchrone, rendant le code beaucoup plus fluide et compréhensible.
Prerequis
- Connaissances en JavaScript (notamment les fonctions fléchées, les promesses)
- Environnement de développement (Node.js recommandé)
Pour installer Node.js :
bash##
Concepts fondamentaux
1. Promesse (Promise)
Une promesse représente une valeur qui peut être disponible maintenant, dans l'avenir ou jamais. Elle a trois états : pending (en attente), fulfilled (réussie) et rejected (échouée).
// Créez une promesse simple
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('La promesse est résolue');
}, 2000);
});
myPromise.then(result => {
console.log(result); // La promesse est résolue
}).catch(error => {
console.error(error);
});
2. Async/Await
Async/Await est une syntaxe plus lisible pour travailler avec des promesses. L'opérateur async indique que la fonction retourne une promesse, et await est utilisé pour attendre que la promesse soit résolue.
// Utilisez async/await avec une promesse
const fetchData = async () => {
const response = await myPromise; // Attendre que la promesse soit résolue
console.log(response); // La promesse est résolue
};
fetchData();
3. Gestion des erreurs
Les erreurs dans les fonctions async/await sont gérées avec un bloc try/catch.
// Gérer les erreurs avec async/await
const fetchData = async () => {
try {
const response = await myPromise; // Attendre que la promesse soit résolue
console.log(response); // La promesse est résolue
} catch (error) {
console.error('Erreur :', error);
}
};
fetchData();
Mise en pratique : projet fil rouge
Nous allons créer un simple gestionnaire de tâches asynchrones. Le projet comprendra les opérations suivantes :
- Ajouter une tâche
- Récupérer toutes les tâches
- Supprimer une tâche
Étape 1 : Structure du projet
Créez un nouveau dossier pour le projet et initialisez-le avec npm init -y.
mkdir task-manager
cd task-manager
npm init -y
Étape 2 : Création des fichiers
Créez les fichiers suivants :
index.jstaskManager.js
Étape 3 : Implémentation du gestionnaire de tâches
taskManager.js
// taskManager.js
class TaskManager {
constructor() {
this.tasks = [];
}
async addTask(task) {
return new Promise((resolve, reject) => {
setTimeout(() => {
this.tasks.push(task);
resolve(`Tâche "${task}" ajoutée`);
}, 1000);
});
}
async getTasks() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(this.tasks);
}, 500);
});
}
async deleteTask(task) {
return new Promise((resolve, reject) => {
const index = this.tasks.indexOf(task);
if (index !== -1) {
this.tasks.splice(index, 1);
resolve(`Tâche "${task}" supprimée`);
} else {
reject(`Tâche "${task}" non trouvée`);
}
});
}
}
module.exports = TaskManager;
index.js
// index.js
const TaskManager = require('./taskManager');
async function main() {
const taskManager = new TaskManager();
try {
await taskManager.addTask('Acheter du pain');
console.log(await taskManager.getTasks());
await taskManager.deleteTask('Acheter du pain');
console.log(await taskManager.getTasks());
} catch (error) {
console.error(error);
}
}
main();
Étape 4 : Exécution du projet
node index.js
Vous devriez voir les tâches ajoutées et supprimées en conséquence.
Erreurs frequentes et debugging
1. Erreur de syntaxe avec await hors d'une fonction async
Code incorrect :
const fetchData = () => {
const response = await fetch('https://api.example.com/data'); // SyntaxError: await is only valid in async function
};
Correction :
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
};
2. Erreur de gestion des erreurs
Code incorrect :
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data'); // Pas de catch pour gérer les erreurs
}
};
Correction :
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('Erreur HTTP : ' + response.status);
}
} catch (error) {
console.error('Erreur :', error);
}
};
3. Erreur de promesse non résolue
Code incorrect :
const fetchData = async () => {
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Réussi');
}, 2000);
});
await promise; // Pas de gestion des erreurs avec catch
};
Correction :
const fetchData = async () => {
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Réussi');
}, 2000);
});
try {
await promise;
} catch (error) {
console.error('Erreur :', error);
}
};
Pour aller plus loin
Promises.all : Utilisez
Promise.allpour exécuter plusieurs promesses en parallèle et attendre que toutes soient résolues.Async/Await avec fetch : Utilisez
async/awaitpour gérer les appels API avecfetch.Axios : Utilisez Axios, une bibliothèque populaire pour les appels API, qui offre une syntaxe plus moderne et intuitive.
Défi pratique
Créez un petit CLI (Command Line Interface) pour gérer des tâches. L'utilisateur devrait pouvoir ajouter, récupérer et supprimer des tâches via la ligne de commande. Utilisez les fonctions du gestionnaire de tâches implémenté précédemment.
Conclusion
Async/Await est une puissance dans la main des développeurs JavaScript qui permet d'écrire du code plus propre et lisible en gérant les opérations asynchrones de manière synchrone. En suivant ce tutoriel, vous devriez être capable de comprendre et d'appliquer cette syntaxe dans vos projets professionnels.
N'oubliez pas, la pratique est la clé pour maîtriser Async/Await. Allez-y et expérimentez avec ces concepts !