Après la mise en place, il est peut-être temps de faire un premier script. J’ai tenté un petit script que j’ai fait la veille en ruby : lister toutes les images dans une hiérarchie de répertoires et faire un gros fichier Json qui récapitule les différentes tailles.
Faire un petit fichier outil CLI à l’aide de commander.js : un callback. Lister les fichiers d’un répertoire : un callback. Lire les exif : un callback. Écrire dans un fichier JSON : un callback.
Bon, lire et écrire peuvent se faire en synchrone sans callback – et dans mon cas précis ça ne changerait probablement rien – mais je suis là aussi pour apprendre comment faire pour plus tard dans cet écosystème.
Une hiérarchie de quatre fonctions de rappel pour ce qui m’a pris 5 à 10 lignes tout mouillé en Ruby, ça me fait mal. J’avoue, je suis presque surpris que la transformation en JSON ne me demande pas un callback.
Me voici en plein callback hell. Le problème est connu. J’ai bêtement pensé qu’on me donnerait une solution rapidement, un outil ou un usage à suivre.
On me pointe vers les promesses ES2015 mais l’API Node et tous les modules en ligne continuent à utiliser des callback. Sérieusement, personne n’a cherché à présenter l’API Node directement en promesses ?
C’est donc à moi de transformer chaque méthode ou chaque module pour qu’il utilise des promesses. Promisify semble être la baguette magique pour ça. À partir de là il suffit de convertir chaque module pour enchaîner des promesses (attention aux écueils).
Franchement ça reste assez moche. Des gens biens me pointent vers les systèmes à base de générateurs (je recommande la lecture de ce lien) et le module co. Le code résultant est déjà bien plus lisible malgré les artifices.
On me rappelle alors les async / await (là aussi, je recommande la lecture). Je crois que c’est seulement maintenant, après cette exploration, que je comprends l’intérêt et le fonctionnement. Parfait, si ce n’est qu’il faut choisir presque au hasard entre trois plugins différents pour ajouter la fonctionnalité à Babel.
Attention, ce n’est pas magique. Il faut se rappeler que ce n’est qu’une surcouche aux promesses, et il y a quelques écueils (lien indispensable si vous comptez utiliser async/await) à bien connaitre là ici aussi, entre autres pour ne pas perdre les exceptions dans un trou noir.
Je me retrouve avec un code qui a l’air relativement élégant mais la réalité me rattrape : Visiblement quasi aucun code en production ne fonctionne ainsi. Une majorité des gens utilisent encore des callbacks, les autres se sont contentés des promesses. Est-ce une bonne idée de déjà viser les async/await ?
Il reste aussi que j’ai l’impression de retrouver le mode multi-tâche coopératif de Microsoft Windows 3.1 en moins bien intégré. Je ne vois aucune raison pour que la bibliothèque standard m’impose des callbacks, des promesses ou des async/await à tout bout de champ plutôt que de gérer ça en interne.
L’OS sait déjà passer à un autre processus quand mon programme est en attente d’une i/o. Si la machine virtuelle du langage veut gérer plusieurs fils d’exécution en interne pour optimiser le processeur, qu’elle le gère elle-même via l’API mise à disposition. C’est à elle d’identifier que je veux ouvrir un fichier et de savoir qu’elle peut favoriser un autre fil d’exécution en attendant que le disque me remonte la donnée. Je trouve ahurissant que ces mécanismes débordent sur mon code et le complexifient ainsi.
Oui, les promesses ne servent pas qu’à gérer la lenteur des i/o et faire coopérer les différents fils d’exécutions de la machine virtuelle V8 mais c’est quand même pour ça qu’on me les impose partout dans l’API de Node.js. Ça en devient même un style de programmation et les modules proposent des callbacks partout et pour tout (à vue de nez, y compris là où ça n’a pas vraiment de sens, à mon humble avis par mimetisme).
Promesses, async, callbacks… J’adore tous ces concepts, mais quand j’en ai besoin moi, pas pour compenser les choix d’architecture du moteur sous-jacent.
Javascript a énormément évolué, dans le bon sens. Côté syntaxe ES2015 et suivant donnent un résultat qui m’attire beaucoup. Le fonctionnement et l’API de Node.js me semblent pour l’instant gâcher tout ce résultat. Un beau langage avec un boulet aux pieds.
Laisser un commentaire