async en JavaScript : écrire de l'asynchrone qui se lit de haut en bas

Le mot-clé async transforme une fonction en fonction asynchrone : elle renvoie toujours une promesse et autorise await dans son corps. Mode d'emploi.
3 min de lecture
Believemy logo

Charger des données, lire un fichier, appeler une API : ces opérations prennent du temps, et JavaScript refuse d'attendre les bras croisés. Pendant des années, la réponse a été d'empiler des fonctions de rappel, avec le code écrit dans un ordre qui n'était plus celui de la lecture.

async a réglé ce problème de présentation. Le code redevient une suite d'instructions lues de haut en bas, alors que le moteur, lui, continue de travailler autrement.


Définition

async se place devant une fonction et change deux choses : la fonction renvoie désormais toujours une Promise, et le mot-clé await devient utilisable dans son corps.

JAVASCRIPT
async function chargeProfil(id) {
  const reponse = await fetch('/api/profil/' + id);
  return reponse.json();
}

chargeProfil(7).then(profil => console.log(profil));

La ligne await ressemble à un appel ordinaire, alors qu'elle met la fonction en pause et rend la main au reste du programme jusqu'à l'arrivée de la réponse.


Ce qu'une fonction async renvoie toujours

C'est la règle qui surprend le plus : quoi que vous écriviez après return, l'appel produit une promesse.

DéclarationCe que l'appel produit
function f() { return 42 }42
async function f() { return 42 }une promesse tenue avec 42
async function f() { throw ... }une promesse rejetée
JAVASCRIPT
async function chiffre() {
  return 42;
}

console.log(chiffre());              // Promise { 42 }
chiffre().then(v => console.log(v)); // 42

Une valeur qui s'affiche comme Promise dans la console vient presque toujours de là : la fonction a été appelée sans await devant.


Les quatre endroits où on l'écrit

  • Devant une déclaration : async function charge() {}.
  • Devant une fonction fléchée : const charge = async () => {}.
  • Devant une méthode, dans une class ou un objet : async charge() {}.
  • Devant une fonction appelée aussitôt : (async () => { ... })(), utile pour ouvrir une zone asynchrone dans un fichier qui ne l'est pas.
Bon à savoir

Un throw dans une fonction async ne remonte pas comme une erreur classique : elle rejette la promesse renvoyée. Elle se rattrape donc avec .catch(), ou avec un try autour de l'appel, à condition que celui-ci soit précédé d'un await.


Questions fréquentes

Question

Faut-il mettre async sur toutes les fonctions ?

Non. Une fonction async qui ne contient aucun await n'apporte rien : elle emballe simplement son résultat dans une promesse, obligeant tous ses appelants à s'adapter. Réservez le mot-clé aux fonctions qui attendent réellement quelque chose.


Question

Est-ce que async ralentit le code ?

Le coût propre du mot-clé est négligeable. Ce qui coûte, c'est la manière dont vous enchaînez les attentes : trois appels attendus l'un après l'autre prennent la somme de leurs durées, alors que les lancer ensemble avec Promise.all() prend celle du plus lent. Le vrai levier de performance est là, jamais dans le mot-clé lui-même.


Question

Peut-on utiliser await sans async ?

Oui, au niveau supérieur d'un module, où await s'écrit directement sans englober le code dans une fonction. Partout ailleurs, notamment dans un script classique, il faut une fonction async. Notre formation JavaScript reprend cet enchaînement depuis les promesses, l'étape que beaucoup sautent avant de se heurter à ces messages d'erreur.

Termes connexes

Découvrez notre glossaire JavaScript

Tous les mots de JavaScript expliqués simplement : mots-clés, objets natifs, méthodes, erreurs et concepts. Définitions claires et exemples qui tournent, pour apprendre et pour se dépanner.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.