Les callbacks
Ils vous permettent de traiter une réponse après l'exécution d'une fonction asynchrone, en cas d'erreur ou non.
Ils ont pour défauts de devoir avoir des fonctions gérant l'échec ou la réussite et de pousser vers un développement plein de fonctions imbriquées, nuisant à sa lisibilité et l'espace des arguments de votre fonction est pollué par les callbacks.
Pour palier cela, une autre méthode est apparue, les promesses (promises, en anglais).
Les promises
Les promesses ont une structure permettant aussi de gérer l'échec ou la réussite de l'exécution d'une fonction, d'exécuter des fonctions pendant la progression de l'exécution, etc.
Elles se différencient par le fait qu'une promesse est un objet auquel on passe tout un tas de fonctions, via ses méthodes, afin de gérer les différents états de l'exécution.
On se retrouve donc avec énormément de fonctions dans son code avec, parfois, des références internes.
Cela a tendance à déstructurer votre code de telle sorte que sa relecture peut devenir une vraie gymnastique cérébrale.
Le mot-clé yield
Me tenant à jour concernant les avancées du JavaScript, j'ai découvert, parmi les propositions de la future norme ECMAScript 6, le mot-clé yield.
Ce mot-clé, une sorte de return particulier, permet de créer des fonctions retournant un générateur, comprenez par là que la liste d'instructions que contient votre fonction fera un arrêt à chaque yield qu'elle contient, jusqu'à ce que vous appeliez le yield suivant, via la méthode next().
Exemple :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | var generate, generator; generate = function generate(value) { yield 'Hello ' + value; }; generator = generate('World'); // on appelle le yield suivant du générateur, après 2 secondes setTimeout(function () { // renverra "Hello World" dans votre console, après les 2 secondes console.log(generator.next()); }, 2000); |
Celle-ci permet d'envoyer une liste de valeurs au générateur, à un moment donné pendant le parcours des yield qu'il contient.
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | var generate, generator; generate = function generate() { var message, response; message = 'Hello '; response = yield message; yield message + response; }; generator = generate(); // on démarre le générateur, affichera "Hello " console.log(generator.next()); // on appelle le yield suivant du générateur, après 2 secondes setTimeout(function () { // renverra "Hello World" dans votre console, après les 2 secondes console.log(generator.send('World')); }, 2000); |
Le yielded style programming
Partant de cette découverte, je me suis dit qu'il devrait être possible d'affecter à une variable du contexte (scope) courant, le résultat d'une fonction asynchrone et d'ensuite poursuivre le processus.
C'est ainsi qu'est né yld (prononcez yielded).
Il s'agit d'un outil vous permettant de transformer un générateur en une liste d'instructions s'exécutant l'une après l'autre, comme s'il s'agissait d'une simple fonction mais attendant la réponse de fonctions asynchrones, quand c'est nécessaire.
De plus, il ajoute une notion de relation entre les différents scopes.
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | var asyncFn1, asyncFn2; asyncFn1 = yld(function (a, b) { var child, response; if (isNaN(a) || isNaN(b)) { // stoppe le processus immédiatement et renvoie une erreur avec le message spécifié this.error = 'Invalid values'; } // this.yld est utilisable comme yld child = yield this.yld(asyncFn2)(a); response = yield child.send(b); console.log(response); // 3 }); asyncFn2 = function (a) { var b, parent; parent = this.parent; // retourne le scope courant au scope parent b = yield parent.send(this); // retourne la réponse au scope parent yield setTimeout(function () { parent.send(a + b); }, 3000); }; asyncFn1(1, 2); |
N.B. : Le mot-clé yield étant une possibilité d'amélioration future du JavaScript, il est possible que yld ne s'exécute pas encore partout, néanmoins, yld est déjà conçu pour pouvoir s'exécuter en navigateur et sous Node.js.
Pour tester les différents exemples, je vous recommande l'utilisation d'un Firefox à jour.
EDIT : Le plus facile, pour vos tests, c'est via la console de Firebug.
Sinon, vous pouvez l'embarquer, dans votre HTML via
Code : | Sélectionner tout |
<script type="application/javascript;version=1.7"></script>
Source : https://github.com/Lcfvs/yld
Malgré l'habitude évidente qu'il vous faudra pour complètement en tirer avantage, trouvez-vous que cela peut réellement améliorer la lisibilité de votre code?
Sinon, qu'y reprochez-vous?