La déclaration async function définit une fonction asynchrone qui renvoie un objet AsyncFunction. Une fonction asynchrone est une fonction qui s'exécute de façon asynchrone grâce à la boucle d'évènement en utilisant une promesse (Promise) comme valeur de retour.

On peut également définir des fonctions asynchrones grâce au constructeur AsyncFunction et via une expression de fonction asynchrone.

Syntaxe

async function name([param[, param[, ... param]]]) {
   instructions
}

Paramètres

name
Le nom de la fonction.
param
Le nom d'un argument à passer à la fonction.
instructions
Les instructions qui composent le corps de la fonction.

Valeur de retour

Une promesse (Promise) qui sera résolue avec la valeur renvoyée par la fonction asynchrone ou qui sera rompue s'il y a une exception non interceptée émise depuis la fonction asynchrone.

Description

Une fonction async peut contenir une expression await qui interrompt l'exécution de la fonction asynchrone et attend la résolution de la promesse passée Promise. La fonction asynchrone reprend ensuite puis renvoie la valeur de résolution.

Le mot-clé await est uniquement valide au sein des fonctions asynchrones. Si ce mot-clé est utilisé en dehors du corps d'une fonction asynchrone, cela provoquera une exception SyntaxError.

Note : Le but des fonctions async/await est de simplifier l'utilisation synchrone des promesses et d'opérer sur des groupes de promesses. De la même façon que les promesses sont semblables à des callbacks structurés, async/await est semblable à la combinaison des générateurs et des promesses.

Exemples

Exemple simple

var resolveAfter2Seconds = function() {
  console.log("Début de la promesse lente");
  return new Promise(resolve => {
    setTimeout(function() {
      resolve(20);
      console.log("Résolution de la promesse lente");
    }, 2000);
  });
};

var resolveAfter1Second = function() {
  console.log("Début de la promesse rapide");
  return new Promise(resolve => {
    setTimeout(function() {
      resolve(10);
      console.log("Résolution de la promesse rapide");
    }, 1000);
  });
};

var sequentialStart = async function() {
  console.log('==Début séquentiel==');
  // Si la valeur de l'expression qui suit l'opérateur await
  // n'est pas une promesse, elle sera convertie en une promesse
  // résolue.
  const slow = await resolveAfter2Seconds();

  const fast = await resolveAfter1Second();
  console.log(slow);
  console.log(fast);
}

var concurrentStart = async function() {
  console.log('==Début concurrentiel avec await==');
  // le minuteur débute immédiatement
  const slow = resolveAfter2Seconds();
  const fast = resolveAfter1Second();

  console.log(await slow);
  // On attend que la promesse lente ait fini
  // même si la promesse rapide a déjà fini !
  console.log(await fast); 
}

var stillSerial = function() {
  console.log('==Début concurrentiel avec Promise.all==');
  Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then((messages) => {
    console.log(messages[0]); // slow
    console.log(messages[1]); // fast
  });
}

var parallel = function() {
  console.log('==En parallèle avec Promise.then==');
  resolveAfter2Seconds().then((message)=>console.log(message)); 
  resolveAfter1Second().then((message)=>console.log(message));
}

sequentialStart(); // affichera "slow" après au moins deux secondes puis "fast" après au moins 1 seconde
// On attend que l'instruction précédent ait terminé
setTimeout(concurrentStart, 4000); // prendra au moins 2 secondes au total
// On attend que l'instruction précédent ait terminé
setTimeout(stillSerial, 7000); // prendra au moins 2 secondes au total
// On attend que l'instruction précédent ait terminé
setTimeout(parallel, 10000); // vraiment exécuté en parallèle

Attention ! Il ne faut pas confondre await et Promise.all().

Dans la fonction sequentialStart, l'exécution est suspendue pendant au moins 2 secondes avec le premier await puis encore une autre seconde avec le second await. Le deuxième minuteur n'est pas déclenché avant que le premier ait été déclenché.

Avec concurrentStart, les deux minuteurs sont créés puis mis en attente avec await. Les minuteurs sont exécutés en parallèles mais les appels avec await sont exécutés en série. Aussi, le second await « attendra » que le premier ait fini. Le code total s'exécute donc en 2 secondes (au moins) plutôt qu'en 3 secondes. On obtient le même résultat avec stillSerial en utilisant Promise.all.

Si on souhaite attendre deux (voire plusieurs) promesses en parallèle, il faudra utiliser Promise.then (voir la fonction parallel dans l'exemple).

Réécrire une chaîne de promesses avec des fonctions asynchrones

Lorsqu'on utilise des API qui renvoient des promesses (cf. Promise), on finit par créer des « chaînes » de promesses et on divise alors une fonction en de nombreux fragments. Prenons l'exemple suivant :

function getProcessedData(url) {
  return downloadData(url) // renvoie une promesse
    .catch(e => {
      return downloadFallbackData(url) // renvoie une promesse
    })
    .then(v => {
      return processDataInWorker(v); // renvoie une promesse
    });
}

On peut réécrire ce fragment de code en une seule fonction asynchrone :

async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url); 
  } catch (e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}

Dans l'exemple précédent, on n'inclue pas d'instruction await dans l'instruction return car la valeur de retour d'une fonction asynchrone est implicitement passée dans la méthode Promise.resolve.

Spécifications

Spécification État Commentaires
ECMAScript Latest Draft (ECMA-262)
La définition de 'async function' dans cette spécification.
Projet  
ECMAScript 2017 (ECMA-262)
La définition de 'async function' dans cette spécification.
Standard Définition initiale.

Compatibilité des navigateurs

Update compatibility data on GitHub
OrdinateurMobileServeur
ChromeEdgeFirefoxInternet ExplorerOperaSafariWebview AndroidChrome pour AndroidEdge MobileFirefox pour AndroidOpera pour AndroidSafari pour iOSSamsung InternetNode.js
Support simpleChrome Support complet 55Edge Support complet OuiFirefox Support complet 52IE Aucun support NonOpera Support complet 42Safari Support complet 10.1WebView Android Support complet OuiChrome Android Support complet 55Edge Mobile Support complet OuiFirefox Android Support complet 52Opera Android Support complet 42Safari iOS Support complet 10.1Samsung Internet Android Support complet 6.0nodejs Support complet 7.6.0
Support complet 7.6.0
Support complet 7.0.0
Désactivée
Désactivée From version 7.0.0: this feature is behind the --harmony runtime flag.

Légende

Support complet  
Support complet
Aucun support  
Aucun support
Une action explicite de l'utilisateur est nécessaire pour activer cette fonctionnalité.
Une action explicite de l'utilisateur est nécessaire pour activer cette fonctionnalité.

Voir aussi

Étiquettes et contributeurs liés au document

Contributeurs à cette page : SphinxKnight, mathieuLrt, Osilos, JulienPradet, vTripes
Dernière mise à jour par : SphinxKnight,