Kodokon kodokon.com

L'asynchrone en pratique

Utilisez async/await dans vos routes et gérez les erreurs asynchrones sans faire tomber le serveur.

10 min · 3 questions

Ouvrir cette leçon dans Kodokon

Vos routes réelles ne renvoient pas des tableaux en mémoire : elles lisent des fichiers, interrogent une base, appellent d'autres API. Toutes ces opérations sont asynchrones. Vous connaissez async/await depuis le parcours JavaScript ; voyons comment les employer proprement dans un serveur. Première bonne nouvelle : une fonction de route peut être async.

JAVASCRIPT
import express from "express";
import { readFile } from "node:fs/promises";

const app = express();

app.get("/report", async (req, res) => {
  const raw = await readFile("report.json", "utf8");
  res.json(JSON.parse(raw));
});

app.listen(3000);

Ce code fonctionne... tant que report.json existe. Si la lecture échoue, la promesse est rejetée et, selon la version d'Express, la requête reste sans réponse ou l'erreur fuit dans les journaux. La règle professionnelle : toute route async gère ses erreurs, avec try/catch et next(error).

JAVASCRIPT
app.get("/report", async (req, res, next) => {
  try {
    const raw = await readFile("report.json", "utf8");
    res.json(JSON.parse(raw));
  } catch (error) {
    next(error);
  }
});

next(error) transmet l'erreur au gestionnaire d'erreurs centralisé. C'est un middleware à quatre paramètres, déclaré après toutes les routes. Un seul endroit pour journaliser et formater les erreurs : voilà ce qui distingue une API maintenable d'un projet de week-end.

JAVASCRIPT
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({
    error: "Erreur interne du serveur"
  });
});
Toujours en dernier, après les routes

Dernier réflexe à acquérir : le parallélisme. Deux opérations indépendantes enchaînées avec deux await s'exécutent l'une après l'autre. Promise.all les lance ensemble : le temps de réponse est celui de la plus lente, pas la somme des deux.

JAVASCRIPT
async function fetchUsers() {
  return [{ id: 1, name: "Ada" }];
}

async function fetchTasks() {
  return [{ id: 1, title: "Relire le code" }];
}

app.get("/dashboard", async (req, res, next) => {
  try {
    const [users, tasks] = await Promise.all([
      fetchUsers(),
      fetchTasks()
    ]);
    res.json({ users, tasks });
  } catch (error) {
    next(error);
  }
});

Quiz de validation

Vérifiez que vous avez bien retenu les points clés de cette leçon.

  1. Dans une route async, que faites-vous d'une erreur attrapée par catch ?
    • L'afficher avec console.log et continuer
    • Appeler next(error) pour la transmettre au gestionnaire d'erreurs
    • Relancer la requête automatiquement
  2. Deux appels asynchrones indépendants doivent s'exécuter le plus vite possible. Quelle approche choisissez-vous ?
    • Les enchaîner avec deux await successifs
    • Les lancer ensemble avec Promise.all
    • Utiliser setTimeout entre les deux
  3. À quoi Express reconnaît-il un middleware de gestion d'erreurs ?
    • À sa signature à quatre paramètres, avec err en premier
    • Au nom de la fonction, qui doit être errorHandler
    • À sa position en tête de fichier