JavaScript async/await

Avant d'expliquer async/await, nous devons comprendre les concepts de programmation asynchrone en JavaScript ; vous pouvez vous référer à :Programmation asynchrone en JavaScript。

JavaScript est un langage mono-thread, ce qui signifie qu'il ne peut exécuter qu'une tâche à la fois. Pour éviter que les tâches de longue durée ne bloquent le thread principal, JavaScript utilise un modèle de programmation asynchrone.

Asynchrone vs synchrone

  • Programmation synchrone: Le code s'exécute séquentiellement, et l'opération suivante ne s'exécute qu'après la fin de la précédente.
  • Programmation asynchrone: Certaines opérations sont placées dans la « file de tâches ». Le thread principal continue d'exécuter le code suivant et traite les tâches de la file lorsque le thread principal est inactif.

Exemples

// Exemple synchrone
console.log('1');
console.log('2');
// Sortie : 1, 2

// Exemple asynchrone
console.log('1');
setTimeout(() => console.log('2'), 0);
console.log('3');
// Sortie : 1, 3, 2

Le problème des fonctions de rappel

Avant async/await, JavaScript utilisait principalement des fonctions de rappel pour gérer les opérations asynchrones, mais cela pouvait conduire à l'« enfer des callbacks ».

Exemples

getData(fonction(a) {
  getMoreData(a, fonction(b) {
    getMoreData(b, fonction(c) {
      getMoreData(c, fonction(d) {
        console.log(d);
      });
    });
  });
});

Cette structure imbriquée rend le code difficile à lire et à maintenir.


Introduction de Promise

ES6 a introduit l'objet Promise pour résoudre le problème de l'enfer des callbacks.

Exemples

fonction getData() {
  return new Promise((resolve, reject) => {
    // Opération asynchrone
    setTimeout(() => resolve('data'), 1000);
  });
}

getData()
  .then(data => {
    console.log(data);
    return getMoreData(data);
  })
  .then(moreData => {
    console.log(moreData);
  })
  .catch(error => {
    console.error(error);
  });

Bien que Promise ait amélioré le problème des callbacks, les appels chaînés then() ne sont toujours pas assez intuitifs.


Syntaxe async/await

ES2017 a introduit async/await, qui est construit sur Promise et fait ressembler le code asynchrone à du code synchrone.

Fonctions async

Ajoutez le mot-clé async avant une déclaration de fonction pour indiquer que la fonction est asynchrone :

async function fetchData() {
  // Corps de la fonction
}

Les fonctions async renvoient toujours une Promise :

  • Si la valeur de retour n'est pas une Promise, elle sera automatiquement encapsulée dans une Promise résolue
  • Si une exception est levée, une Promise rejetée est renvoyée

Expressions await

await ne peut être utilisé qu'à l'intérieur de fonctions async :

async function fetchData() {
  const result = await somePromise;
  console.log(result);
}

await met en pause l'exécution de la fonction async jusqu'à ce que la Promise soit réglée :

  • Si la Promise est résolue, la valeur résolue est renvoyée
  • Si la Promise est rejetée, une erreur est levée (qui peut être interceptée avec try/catch)

Exemples d'applications pratiques

Utilisation de base

Exemples

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function showMessage() {
  console.log('Start');
  await delay(1000);
  console.log('After 1 second');
  await delay(1000);
  console.log('Après encore 1 seconde');
}

showMessage();

Gestion des erreurs

Exemples

async function fetchUserData() {
  try {
    const response = await fetch('https://api.example.com/user');
    if (!response.ok) {
      throw new Error('La réponse du réseau n'est pas correcte');
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Échec de la récupération des données :', error);
  }
}

Exécution parallèle

Si vous devez exécuter plusieurs opérations asynchrones en parallèle, vous pouvez utiliser Promise.all :

Exemples

async function fetchMultipleData() {
  const [userData, productData] = await Promise.all([
    fetch('/api/user'),
    fetch('/api/products')
  ]);
 
  const user = await userData.json();
  const products = await productData.json();
 
  return { user, products };
}

Problèmes courants et bonnes pratiques

1. N'oubliez pas await

Exemples

// Exemple incorrect - oubli d'await
async function example() {
  const data = fetch('/api'); // await manquant
  console.log(data); // Affiche un objet Promise
}

// Exemple correct
async function example() {
  const data = await fetch('/api');
  console.log(data); // Affiche les données réelles
}

2. Éviter l'async inutile

Exemples

// Pas nécessaire - aucun await dans la fonction
async function unnecessaryAsync() {
  return 42;
}

// Manière plus simple de l'écrire
function simpleFunction() {
  return 42;
}

3. await de premier niveau

await peut être utilisé directement au niveau supérieur d'un module (fonctionnalité ES2022) :

Exemples

// Dans un module
const data = await fetch('/api');
console.log(data);

4. Considérations sur les performances

  • Exécution séquentielle vs exécution parallèle : utilisez Promise.all de manière appropriée pour améliorer les performances
  • Gestion des erreurs : assurez-vous que toutes les erreurs possibles sont capturées

async/await vs Promise traditionnelle

Fonctionnalité async/await Promise then/catch
Lisibilité Élevée, similaire au code synchrone Moyenne, appels chaînés
Gestion des erreurs Utilise try/catch Utilise .catch()
Débogage Plus facile, avec une pile d'appels claire Plus difficile, la pile d'appels peut être floue
Structure du code Plus plate Imbriquée ou chaînée

Résumé

async/await est une amélioration majeure de la programmation asynchrone en JavaScript. Il :

  1. Rend le code asynchrone plus lisible et plus maintenable
  2. Est basé sur Promise et compatible avec le code Promise existant
  3. Fournit une manière plus intuitive de gérer les erreurs
  4. Améliore l'expérience de débogage

Bien que async/await ne remplace pas complètement Promise, dans la plupart des cas, cela offre une solution plus élégante. Comprendre comment async/await fonctionne et ses bonnes pratiques améliorera grandement vos compétences en programmation asynchrone JavaScript.

Autres extensions