Async, Promises et Fetch : l'IA démystifie l'asynchrone

Comprenez enfin l'asynchrone en JavaScript grâce aux LLM. Promises, async/await et fetch API expliqués avec des prompts efficaces et des exemples concrets.

L'asynchrone : le mur que tout débutant rencontre

Quatrieme article de la serie "Apprendre JavaScript avec l'IA". Si tu debutes, lis d'abord les articles sur les bases et le DOM.

L'asynchrone est le concept qui bloque le plus de développeurs débutants. Le code semble s'exécuter dans le désordre, on voit des then, des await, des Promise, et on ne comprend plus rien. J'ai personnellement mis des semaines a comprendre ca en 2019. Avec un LLM, tu peux y arriver en un apres-midi -- si tu poses les bonnes questions.

Pourquoi JavaScript a besoin de code asynchrone

JavaScript est mono-thread. Un seul fil d'exécution, pas de parallélisme natif. Si une opération prend 3 secondes (une requête réseau, la lecture d'un fichier), tout le reste est bloque : pas de scroll, pas de clic, la page est gelee.

"Explique-moi pourquoi JavaScript a besoin de code asynchrone. Utilise une analogie avec un restaurant."

L'analogie classique : un restaurant avec un seul serveur. S'il attend devant la cuisine que chaque plat soit pret avant de prendre la commande suivante, les clients attendent une heure. A la place, il prend la commande, la transmet en cuisine, et passe au client suivant. Quand le plat est pret, il le livre.

JavaScript fait pareil. Il lance une opération (requête réseau), passe a la suite, et revient quand le résultat est disponible.

Les callbacks : la première solution

Les callbacks, c'est le principe de base : tu passes une fonction en argument, et elle sera appelee quand l'opération sera terminee.

javascriptfunction telechargerDonnees(url, callback) {
  setTimeout(() => {
    const donnees = { nom: "JavaScript", version: "ES2025" };
    callback(donnees);
  }, 1000);
}

telechargerDonnees("https://api.exemple.com", (resultat) => {
  console.log(resultat); // s'affiche apres 1 seconde
});
console.log("Ca s'affiche en premier !"); // s'affiche tout de suite

Ca marche pour un seul appel. Mais enchaîné-en quatre :

javascript// Le "callback hell" - la pyramide de la mort
telechargerUtilisateur(id, (utilisateur) => {
  telechargerPosts(utilisateur.id, (posts) => {
    telechargerCommentaires(posts[0].id, (commentaires) => {
      telechargerAuteur(commentaires[0].auteurId, (auteur) => {
        console.log(auteur.nom);
        // 4 niveaux d'indentation, illisible
      });
    });
  });
});

Illisible. Impossible a debugger. C'est pour ca que les Promises existent.

Les Promises : la solution lisible

Une Promise represente une valeur qui n'existe pas encore mais existera plus tard. Elle a trois états : pending (en cours), fulfilled (reussie) ou rejected (echouee). Elle ne peut changer d'état qu'une seule fois.

"Montre-moi comment créer une Promise, la chainer avec then, et gerer les erreurs avec catch. Donne un exemple realiste, pas avec setTimeout."

javascriptfunction telechargerDonnees(url) {
  return new Promise((resolve, reject) => {
    // Simule un appel reseau
    setTimeout(() => {
      if (url.startsWith("https")) {
        resolve({ nom: "JavaScript", version: "ES2025" });
      } else {
        reject(new Error("URL non securisee"));
      }
    }, 1000);
  });
}

telechargerDonnees("https://api.exemple.com")
  .then((donnees) => {
    console.log("Recu :", donnees.nom);
    return donnees.version;
  })
  .then((version) => {
    console.log("Version :", version);
  })
  .catch((erreur) => {
    console.error("Echec :", erreur.message);
  });

Le chainage avec .then() est deja plus lisible que les callbacks imbriques. Mais async/await va encore plus loin.

async/await : le code asynchrone qui se lit comme du synchrone

async/await est du sucre syntaxique au-dessus des Promises. Sous le capot, c'est exactement la meme chose. Mais la lisibilité est incomparable.

javascript// Avec .then() - lisible mais verbeux
function chargerProfil() {
  return telechargerUtilisateur(42)
    .then((user) => telechargerPosts(user.id))
    .then((posts) => telechargerCommentaires(posts[0].id))
    .then((commentaires) => console.log(commentaires))
    .catch((err) => console.error(err));
}

// Avec async/await - se lit de haut en bas
async function chargerProfil() {
  try {
    const user = await telechargerUtilisateur(42);
    const posts = await telechargerPosts(user.id);
    const commentaires = await telechargerCommentaires(posts[0].id);
    console.log(commentaires);
  } catch (err) {
    console.error(err);
  }
}

Le code async/await se lit comme du code normal. C'est pour ca qu'il est devenu le standard en 2026.

Le piège du await en boucle (l'IA généré souvent ce bug)

Voici un problème que j'ai vu Claude et ChatGPT générer des dizaines de fois :

javascript// LENT : les requetes s'executent une par une
async function chargerArticles(ids) {
  const articles = [];
  for (const id of ids) {
    const article = await telechargerArticle(id); // attend chaque fois
    articles.push(article);
  }
  return articles;
}
// 10 articles x 500ms = 5 secondes

// RAPIDE : les requetes partent en parallele
async function chargerArticles(ids) {
  const promesses = ids.map((id) => telechargerArticle(id));
  return await Promise.all(promesses);
}
// 10 articles en parallele = 500ms

Dix fois plus rapide. C'est une différence énorme. Quand tu vois un await dans une boucle for, c'est un signal d'alarme. Demande a l'IA :

"Ce code avec await dans une boucle for est-il optimal ? Montre-moi la version avec Promise.all."

Fetch API : les requêtes HTTP en pratique

fetch est l'API native du navigateur pour les requêtes HTTP. Elle retourne une Promise, donc tout ce qu'on vient de voir s'applique.

javascriptasync function recupererUtilisateurs() {
  try {
    const reponse = await fetch("https://jsonplaceholder.typicode.com/users");

    // PIEGE : fetch ne rejette PAS sur les erreurs HTTP
    if (!reponse.ok) {
      throw new Error(`Erreur HTTP : ${reponse.status}`);
    }

    const utilisateurs = await reponse.json();
    return utilisateurs;
  } catch (erreur) {
    console.error("Echec :", erreur.message);
    return [];
  }
}

Le piège que l'IA oublie presque toujours

fetch ne lance pas d'erreur quand le serveur renvoie un 404 ou un 500. Il considéré que la requête a "reussi" (il a reçu une réponse). Seule une erreur réseau (serveur injoignable, pas de connexion) déclenché un reject.

Ca veut dire que ce code a un bug :

javascript// Bug : pas de verification de response.ok
async function getData() {
  try {
    const res = await fetch("/api/users");
    const data = await res.json(); // plante si le serveur renvoie du HTML 404
    return data;
  } catch (err) {
    console.error(err); // n'attrape PAS les erreurs 404/500
  }
}

J'ai demande a ChatGPT de générer du code avec fetch 20 fois. Sur ces 20 fois, il a oublie response.ok 7 fois. Sept sur vingt. Verifie toujours.

"Pourquoi fetch ne lance pas d'erreur sur un 404 ? Comment gerer correctement les erreurs HTTP ?"

Exemple complet : recherche avec debounce et fetch

Voici un composant realiste qui combine DOM, événements, debounce et fetch :

javascriptconst champRecherche = document.getElementById("recherche");
const resultats = document.getElementById("resultats");

async function rechercher(terme) {
  resultats.textContent = "Chargement...";

  try {
    const reponse = await fetch(
      `https://api.exemple.com/search?q=${encodeURIComponent(terme)}`
    );
    if (!reponse.ok) throw new Error(`Erreur ${reponse.status}`);

    const donnees = await reponse.json();
    resultats.innerHTML = "";
    donnees.forEach((item) => {
      const li = document.createElement("li");
      li.textContent = item.titre;
      resultats.appendChild(li);
    });
  } catch (erreur) {
    resultats.textContent = `Erreur : ${erreur.message}`;
  }
}

let timer;
champRecherche.addEventListener("input", (e) => {
  clearTimeout(timer);
  timer = setTimeout(() => {
    if (e.target.value.length >= 3) {
      rechercher(e.target.value);
    }
  }, 400);
});

Ce code utilise tout ce qu'on a vu dans la serie. Si tu comprends chaque ligne, t'es pret pour le projet final.

Exercice : corriger le code de l'IA

Demande a ton LLM :

"Cree une fonction JavaScript qui telecharge 5 images en parallèle depuis des URLs et les affiche dans la page."

Analyse la réponse :

  • Les images sont-elles chargees en parallèle avec Promise.all ou Promise.allSettled ?
  • Les erreurs sont-elles gerees individuellement (une image qui echoue ne devrait pas bloquer les autres) ?
  • response.ok est-il vérifié ?

Si la réponse a des failles, corrige-les toi-meme. C'est exactement le type d'automatisation workflow qu'on pratique au quotidien chez paltemps.fr.

La suite

Dernier article de la serie : on construit un projet complet avec Ollama. Backend Node.js, frontend vanilla JS, connexion a un LLM local. Tout ce qu'on a appris, rassemble dans une app fonctionnelle.

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.