Utiliser async et await dans un contrôleur
Objectif : Attendre un résultat de service avant de construire la réponse HTTP.
Quand une route dépend d’un résultat asynchrone, vous devez envoyer sa réponse HTTP après que ce résultat est disponible. Si vous construisez la réponse trop tôt, vous risquez de renvoyer une valeur incomplète ou une promesse au lieu des données attendues. Vous allez remplacer l’enchaînement avec then du contrôleur des commandes par async et await, sans déplacer le travail du service.
Le service des commandes retourne déjà une promesse qui se résout avec un tableau vide, comme vu dans la leçon précédente. Vous conservez cette responsabilité : le service fournit les données, et le contrôleur se charge de la réponse HTTP. La route et le serveur ne changent pas.
Déclarer un contrôleur asynchrone
Le mot-clé async placé devant une fonction indique que celle-ci exécute un traitement asynchrone. Une fonction async retourne toujours une promesse, même si son corps retourne une valeur ordinaire. Dans ce contrôleur, vous utilisez await devant l’appel au service : l’exécution de la fonction attend la résolution de la promesse avant de passer à la ligne suivante.
const commandesService = require('../services/commandes');
async function lister(req, res) {
const commandes = await commandesService.lister();
res.json({
donnees: commandes,
erreur: null
});
}
module.exports = {
lister
};La variable commandes contient ici la valeur résolue par la promesse du service, et non la promesse elle-même. Le contrôleur peut donc transmettre directement ce tableau dans le champ donnees. La structure normalisée des réponses a été établie dans la leçon « Lire les requêtes et formater les réponses » ; elle reste identique, que le résultat soit obtenu de façon synchrone ou asynchrone.
Le service reste la source du résultat
Le fichier du service peut rester tel qu’il est à la fin de la leçon précédente. Le voici en entier pour situer l’appel attendu par le contrôleur. Vous pourrez remplacer plus tard cette source provisoire par un accès aux données asynchrone sans changer le format de réponse construit ici.
function lister() {
return Promise.resolve([]);
}
module.exports = {
lister
};L’appel suit un ordre précis : le contrôleur commence, appelle lister(), puis suspend la suite de sa fonction sur await. Lorsque la promesse est résolue, l’exécution reprend avec le tableau reçu et res.json() envoie la réponse. Comme le service retourne [] dans cette version du projet, le corps HTTP attendu est le suivant.
Vérifier l’intégration avec la route
Le routeur des commandes associe déjà la méthode GET de sa racine à la fonction exportée lister. L’export garde le même nom, et la fonction reçoit toujours les objets req et res attendus par Express : vous n’avez donc pas besoin de modifier la route ni son montage dans serveur.js. Le préfixe existant expose la liste à l’adresse GET /api/commandes.
Cette version couvre le chemin où le service réussit. Si sa promesse est rejetée, le contrôleur asynchrone ne produit pas la réponse JSON de succès : la prise en charge cohérente de ce cas dépend notamment de la version d’Express utilisée. Vous traiterez ce parcours dans la prochaine leçon, consacrée à la transmission centralisée des erreurs asynchrones ; n’ajoutez pas de blocs try/catch répétitifs dans chaque contrôleur.
À retenir
- Déclarez le contrôleur avec `async` pour pouvoir y utiliser `await`.
- Placez `await` sur l’appel au service dont le résultat est nécessaire à la réponse.
- Construisez la réponse JSON après la résolution de la promesse, en conservant la forme normalisée.
- Gardez l’opération de données dans le service ; les routes existantes continuent d’appeler le contrôleur exporté.
- Le traitement des rejets asynchrones sera centralisé dans la prochaine leçon.