Q chainé ou Q groupé ?

Suite à quelques commentaires sur l'article précédent, j'ai fait quelques tests afin de vérifier que je disais pas trop de conneries. À priori, je me débrouille bien. Voici le test effectué :

  • une fonction promise qui retourne évidemment une promise et dont le traitement asynchrone est de résoudre la promise en renvoyant la variable passée en paramètre au bout d'un temps aléatoire en utilisant setTimeout et Math.random.
  • J'appelle ensuite cette méthode pour chaque lettre de l'alphabet. Étant donné que le setTimeout est aléatoire, je ne suis pas sensé avoir les lettres dans le bon ordre si l'ordre des promises n'était pas respecté.
  • J'ai d'abord utilisé la technique d'enchainement des promises comme présenté dans mon précédent article et nous verrons pourquoi dans cet exemple précis c'est la meilleure technique à utiliser,
  • puis j'ai ensuite utilisé la technique de regroupement des promises à l'aide de Q.all qui sera le sujet d'un prochain article et nous verrons que c'est une très mauvaise idée pour cet exemple, mais une très bonne pour d'autres cas comme celui du précédent article.

Donc dans les deux exemples, on teste qu'on a bien concaténé toutes les lettres de l'alphabet dans le bon ordre. Ce qui est le cas. Mission accomplie.

Si on lance le script, nous aurons dans la console les données suivantes :

  • des lettres dans un ordre aléatoire. C'est le résultat du contre exemple qui lance toutes les requetes en même temps et qui permet donc de prouver que promise() retourne bien son résultat dans un temps aléatoire.
  • "Grouping is : true" : qui prouve que la méthode de regroupement de promesses a bien fonctionné.
  • "Chaining is : true" qui prouve que la méthode par enchainement a bien fonctionné aussi.

Ce qui est intéressant, c'est de voir que la méthode Grouping se termine toujours beaucoup plus rapidement que la méthode Chaining. En fait, Q.all lance toutes les requêtes en même temps, ordonne les résultats dans un tableau dans le même ordre qu'en entrée, puis une fois toutes les requêtes terminées, il appelle le then(). Ça veut donc dire que tous les setTimeout, même s'ils ont une valeur différente, partent au même moment.
Contrairement à la méthode chainée qui va lancer le setTimeout suivant seulement une fois que le précédent est terminé.

Pour conclure, la méthode chainée est moins jolie, mais elle est nécéssaire quand on a besoin du résultat de la précédente méthode pour la méthode suivante ou qu'on ne veut pas tuer le runtime en lui faisant exécuter trop de requêtes en même temps. La méthode groupée est parfaite dans le cas contraire.

Exemples :

  • je veux lire et concaténer des fichiers, j'utiliser Q.all.
  • je veux faire une requete pour locker un fichier, puis une autre requête dans une base de données pour trouver un enregistrement, une autre requête si un enregistrement est trouvé pour l'altérer puis une dernière requête pour locker un fichier, alors j'utiliserais un enchainement de Q.

Hadrien

Hi, I'm a french Javascript Lead Developer, Web Architect from Toulouse, France. I've worked for 12 years for many projects with YUI, AngularJS, Aurelia.io and now React and React native.

Toulouse, France https://hadrien.eu