IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Découvrez le yielded style ou développement JavaScript asynchrone linéaire

Le , par Lcf.vs

21PARTAGES

Si vous avez déjà fait du JavaScript asynchrone, vous avez certainement connaissance de techniques de traitement de la réponse.

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);
Ces générateurs ont aussi une une méthode send().

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);
Enfin, sachez que les générateurs ont aussi une méthode close(), afin de libérer la mémoire.

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);
Comme vous pouvez le constater, il n'y a que très peu de fonctions, vous passez uniquement les arguments dont vos fonctions ont besoin et, surtout, le processus s'interrompt à chaque yield, vous permettant de récupérer une valeur sur la même ligne que l'appel à une fonction asynchrone, comme si elle ne l'était pas.

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>
Où le 1.7 est, évidemment, la version minimale.

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?

Une erreur dans cette actualité ? Signalez-nous-la !