Async, await, de belles promesses ?

Billet dédié à des outils javaScript qui peuvent changer la vie…

LA notion : l’asynchrone

Les promesses en javaScript permettent de faire ce que l’on appelle de l’asynchrone. Ce mot est très important dans le langage.

Pour les curieux(ses) / impatients/ impatientes, voici la doc.

Introduction douce à un concept dur

De base, le moteur de javaScript est monotâche. Il a une pile de tâches à faire et il les dépile au fur et à mesure. Or dans l’idée générale, on associe souvent la notion de multi-tâches à celle d’asynchrone, on parle aussi de tâches en parallèle.

Ces concepts sont piégeux en javaScript.

L’asynchrone par les callbacks

Ne vous basez pas sur ce vous pourriez déduire vaguement des mots en français. Le plus important est de comprendre que javaScript est non bloquant.

Prenez les callbacks (littéralement “fonctions de rappel”), grâce à eux, on peut savoir quand le résultat d’une fonction est disponible et l’exécuter à ce moment. C’est ça que ça veut dire, ça pointe vers une fonction qui ne s’exécute que lorsque le résultat est disponible.

Attention quand je dis “résultat” cela peut être une erreur aussi, mais en tous les cas un retour.

L’image la plus parlante est celle du répondeur, on laisse un message et on est rappelé plus tard.

Partout, dans les frameworks, dans les librairies, on se branche via des callbacks. On passe des fonctions en arguments d’autres fonctions. Ces fonctions passées en argument sont exécutées plus tard.

Elles sont placées dans une sorte de file d’attente par un mécanisme appelé boucle des événements. Dès que le résultat sur lequel elles se fondent est disponible. Prenez ce code jQuery :

$.ajax({
    url: url,
    data: data,
    success: function(data){
        console.log(data);
    },
});

Ton callback servira les cafés en enfer !

Notion bien connue dans le monde javaScript, le callback hell, intervient quand on a mal fait son taf. Certains vont jusqu’à déconseiller d’imbriquer les fonctions de peur de tomber dans le trou qui mène au grand cornu.

Source

Promesses vs callbacks ?

Les callbacks sont pratiques, notamment quand ils sont utilisés avec addEventListener(), car en général on sait ce qui se passe. On colle ça sur le clic d’un bouton par exemple et on gère avec l’événement.

C’est plus problématique lorsqu’on dialogue avec des APIs externes car il faut bien traiter tous les cas de succès, d’erreur. On se retrouve vite avec des imbrications de fonctions imbittables.

Avec les promesses, c’est plus lisible :

const newPromise = new Promise((resolve, reject) => {
   if( /* condition succès */ ) {
     resolve(value); // succès
   } else {
     reject("message d'erreur"); // erreur
   }
});

c’est assez fluide, ensuite on peut tester nos différents cas :

newPromise('https://monapipreferee.com/v1/lol')
.then(function (response) {
  // succès
  console.log(response);
}).catch(function (err) {
  // erreur
  console.log(err);
})

ici response et err afficheront respectivement les résultats de resolve() et reject().

Source (lien google très très bien fait !)

Et vinrent async et await

Des promesses, des promessses… faut que ça cesse !

Ou pas !

Les promesses améliorent les choses mais on peut toujours finir en enfer en imbriquant/chaînant les promesses… Le problème persiste décidément !

async et await taclent bien le souci.

Bon là, on peut pas faire plus clair dans le côté aynchrone. Ces nouveaux mots-clés améliorent encore la lisibilité. Rien qu’avec async placé devant la déclaration de notre fonction, on renvoie directement une promesse.

C’est un peu comme avoir le beurre, l’argent du beurre et le cul de la crémière.

Async

async function myAsyncFunction() {
  return 73;
}

myAsyncFunction().then(console.log);

élégant ! (le code pas ma formule précédente je l’admets XD)

Await

Et en ce qui concerne await, il permet d’attendre qu’une promessse retourne un résultat. Prenons un cas plus parlant de la vie de tous les jours du dév :

async function getDataAsync(id) 
{
  let response = await fetch(`https://monapipreferee.com/data/${id}`);
  let data = await response.json()
  return data;
}

getDataAsync('monId')
  .then(data => console.log(data)); 

Can I Use ?

Suivez ce lien mais oubliez Internet Explorer et quelques autres anciens ! Mais en même temps IE est en fin de piste !

Conclusion

Passez à async/await si votre js contient du code bloquant comme des appels API mais retenez bien qu’on est sur du séquentiel. La parallelisation est un autre sujet, pour cela les dev js utilisent plutôt Promise.all().