Async/Await en JavaScript: exemples
Utiliser des fonctions asynchrones de façon synchrone quand c'est nécessaire est maintenant possible...
Les règles d'utilisation de cette fonctionnalité sont les suivantes:
- Si l'appel d'une fonction est précédé du mot réservé await, les instructions qui suivent cet appel ne sont pas exécutées tant que la fonction n'a pas retourné une valeur. C'est le principe du mode synchrone.
- await ne peut être placé que dans une fonction, et cette fonction doit être déclarée avec le mot réservé async. (Cela peut être une fonction main qui contient tout le programme).
- La fonction appelée doit s'exécuter à l'intérieur du corps d'un objet Promise. Cet objet peut être placé dans la fonction appelée ou alors c'est l'appel de la fonction qui doit être placé dedans, au choix.
La syntaxe est donc la suivante:
function f1() {
... corps de la fonction appelée...
}
async function f2() {
var x = await new Promise(function(resolve) {
resolve( f1() )
} );
...instructions suivantes, utilisant x...
}
f2()
Le paramètre resolve est un callback, et la valeur de retour de cette fonction sera la valeur de retour de f2.
Cette syntaxe convient si on utilise les fonctions d'une bibliothèque qu'on ne peut pas modifier.
L'alternative si on peut modifier la fonction appelée:
function f1() {
return new Promise(function(resolve) {
... corps de la fonction appelée...
});
}
async function f2() {
var x = await f1()
... instructions suivantes, utilisant x...
}
f2()
Cette alternative convient quand on définit soi-même les fonctions et qu'on les veut synchrones.
Il faut noter que si les instructions qui suivent l'appel de f1 dans f2 ne sont pas exécutée avant le retour de f1, ce n'est pas le cas des instructions qui suivent l'appel de f2. Elles seront exécutées avant le retour de f1 et de f2.
Exemple avec une fonction asynchrone
La commande setTimeout n'est là que pour la démonstration, pour ajouter un délai et vérifier que l'on attend bien le retour de l'appel avant d'exécuter les instructions suivantes, en l'occurence avant d'afficher le résultat du calcul de la suite de Fibonacci.
function fibo(n) {
if (n < 2) return n
return fibo(n-2) + fibo(n-1)
}
async function getFibo(n) {
var f = await new Promise(function(resolve) {
setTimeout(function() { resolve(fibo(n)) }, 2000)
});
document.getElementById("storage1").innerHTML = ("Fibo=" + f)
}
getFibo(20)
Si on n'avait pas ajouté await, la commande d'impression du résultat aurait affiché undefined ou Object[Promise].
Exemple avec une fonction synchrone
Cette fois on place l'objet Promise dans la fonction appelée, ce sera plus pratique si on l'appelle plusieurs fois.
function fibo(n) {
if (n < 2) return n
return fibo(n-2) + fibo(n-1)
}
function pFibo(n) {
var p = new Promise(
function(resolve) {
setTimeout(function() { resolve(fibo(n)) }, 1000)
}
)
return p
}
async function getFibo(n) {
var f = await pFibo(n)
document.getElementById("storage2").innerHTML = ("Fibo=" + f)
}
getFibo(20)
On ne peut pas placer l'objet Promise directement dans Fibo qui est une fonction récursive, c'est pourquoi on crée une fonction intermédiaire. On procèdera de même pour les fonctions d'une bibliothèque qu'on ne peut modifier.
Voir aussi:
- Promise. Enchaîner des Promises est plus clair qu'imbriquer des callbacks.
- JavaScript sans callback. Async/await est un des moyens de supprimer les callbacks imbriqués.