Écris du code asynchrone plus propre en utilisant les fonctions async et le mot-clé await comme sucre syntaxique par-dessus les Promises.
Le mot-clé async placé avant une déclaration de fonction crée une fonction async. Les fonctions async retournent toujours une Promise — même si tu retournes une valeur simple, elle est automatiquement enveloppée dans Promise.resolve().
Déclaration de fonction :
async function fetchData() {
return 'Hello';
}
fetchData().then(value => console.log(value)); // 'Hello'Expression de fonction :
const fetchData = async function() {
return 'Hello';
};Fonction flèche :
const fetchData = async () => {
return 'Hello';
};Méthode d'objet :
const api = {
async getData() {
return 'data';
}
};Comme les fonctions async retournent des Promises, tu peux utiliser .then() sur le résultat. Mais la vraie puissance vient de l'utilisation de await à l'intérieur.
Le mot-clé await ne peut être utilisé qu'à l'intérieur d'une fonction async (ou au niveau supérieur d'un module ES). Il met en pause l'exécution de la fonction async jusqu'à ce que la Promise qu'il attend soit résolue.
async function loadUser() {
const response = await fetch('/api/user');
const user = await response.json();
console.log(user.name);
}Sans await, le même code utilisant .then() ressemblerait à ceci :
function loadUser() {
return fetch('/api/user')
.then(response => response.json())
.then(user => console.log(user.name));
}Points clés :
await met en pause uniquement la fonction async — le reste de ton code continue de s'exécuter.await lance la raison du rejet comme une erreur.await n'importe quelle valeur, pas seulement des Promises — les valeurs non-Promise sont retournées immédiatement.async function demo() {
const a = await 42; // Se résout immédiatement à 42
const b = await Promise.resolve('hello'); // Se résout à 'hello'
console.log(a, b); // 42 'hello'
}Avec les Promises, tu gères les erreurs en utilisant .catch(). Avec async/await, tu utilises plutôt l'instruction familière try/catch.
async function loadData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Échec du chargement:', error.message);
}
}Tu peux envelopper plusieurs appels await dans un seul bloc try. Si l'un d'eux est rejeté, l'exécution saute au bloc catch :
async function processOrder() {
try {
const user = await getUser();
const order = await createOrder(user.id);
const receipt = await sendReceipt(order.id);
return receipt;
} catch (error) {
// Gère les erreurs de N'IMPORTE LEQUEL des trois appels await
console.error('Échec de la commande:', error);
}
}Tu peux aussi ajouter un bloc finally pour le nettoyage qui s'exécute peu importe le succès ou l'échec :
async function fetchWithLoading() {
showSpinner();
try {
const data = await fetchData();
displayData(data);
} catch (error) {
showError(error);
} finally {
hideSpinner(); // S'exécute toujours
}
}La combinaison de async/await + try/catch est le standard moderne pour gérer les erreurs asynchrones en JavaScript.
Exécution séquentielle vs parallèle :
Quand tu await plusieurs Promises l'une après l'autre, elles s'exécutent séquentiellement (chacune attend que la précédente se termine) :
// Séquentiel — prend ~2 secondes au total
const user = await fetchUser(); // 1 seconde
const orders = await fetchOrders(); // 1 secondeSi les opérations sont indépendantes, utilise Promise.all() pour les exécuter en parallèle :
// Parallèle — prend ~1 seconde au total
const [user, orders] = await Promise.all([
fetchUser(),
fetchOrders()
]);Évite l'anti-pattern « cascade » quand les opérations ne dépendent pas les unes des autres.
Async IIFE — fonction async immédiatement invoquée pour une exécution rapide :
(async () => {
const data = await fetchData();
console.log(data);
})();Top-level await — dans les modules ES, tu peux utiliser await au niveau supérieur sans l'envelopper dans une fonction async :
// Dans un module ES (.mjs ou type="module")
const data = await fetchData();
console.log(data);Le top-level await est utile dans le code d'initialisation de module mais doit être utilisé avec précaution car il bloque le chargement complet du module jusqu'à ce que la Promise soit résolue.
<div id="output"></div>
<script>
// Simulate an API call
function simulateAPI(data, delay) {
return new Promise(resolve => {
setTimeout(() => resolve(data), delay);
});
}
const output = document.getElementById('output');
output.innerHTML = '<p>Loading...</p>';
async function loadDashboard() {
try {
// Run in parallel with Promise.all
const [user, settings] = await Promise.all([
simulateAPI({ name: 'Alice' }, 300),
simulateAPI({ theme: 'dark' }, 200)
]);
output.innerHTML = `
<p>User: ${user.name}</p>
<p>Theme: ${settings.theme}</p>
<p>Dashboard loaded!</p>
`;
} catch (error) {
output.innerHTML = `<p>Error: ${error.message}</p>`;
}
}
loadDashboard();
</script>Que fait le mot-clé await ?