dimanche 19 février 2012

3 conseils de survie pour la programmation asynchrone


Basculer vers le coté obscur de la programmation asynchrone avec node.js  n'est pas sans danger.
Voici trois conseils de jeidi ou de ninja.

Conseil 1: Asynchrone tu penseras
 En asynchrone l'enchaînement des opérations n'est pas linéaire. Pour dérouler les opérations A,B,C dans cet ordre vous aurez le choix entre 2 techniques:
1) L'imbrication des callback .
La dernière instruction de la fonction A appellera la fonction B , la fonction B à son tour appellera C dans sa dernière instruction.

Cette méthode a deux limites. 
a) Il faut s'assurer que la fonction A utilise des composants synchrones afin d'éviter que la fonction B démarre avant la réponse de la fonction A.
b) L'imbrication des fonctions au delà de 3 niveaux rend le code difficile à lire.

2) la gestion des enchaînements par événement.
La fonction B démarrera à la réception d'un événement déclenché par la fonction A.
Cette  approche est peut être moins performante mais permet de rendre le code plus lisible en évitant l'imbrication des fonctions.

Conseil 2: Synchrone  tu anticiperas
Une fonction asynchrone bien écrite se comportera toujours de manière asynchrone. Ce n'est pas forcement le cas de toutes les librairies.  Une fonction asynchrone peut  réagir comme une fonction synchrone dans certaines circonstances comme par exemple :
Utilisation d'un cache
Erreur de connexion
Prenons l'exemple d'une requete sur une base de données: normalement il est sensé s'ecouler un certain nombre de cycle avant d'obtenir la réponse. Ces cycle correspondant à une tour de la boucle de traitement est appelé 'tick'. Si la fonction de requete à mis en cache la réponse, elle pourra réponde dans le même cycle comme une fonction synchrone. Aussi , il est recommandé de placer au plus tôt et au plus près   les 'listeners' . Dans le même ordre d'idée, on évitera les appels chainés de méthode.  On peut se trouver dans le cas  d'appels de méthode sur des objets non encore instanciés.
exemple :
var client = net.connect(8124, function() {
    console
.log('client connected');
    client
.write('world!\r\n');
});
(code tiré de :Understanding process.nextTick()  )
Ici la l'objet client utilisé dans le callback peut ne pas etre crée si la connexion est  immédiate (meme tick).
 Une API  asynchrone bien écrite peut éviter un comportement synchrone en utilisant la fonction nextTick().  Cette fonction déporte l'exécution d'une fonction au prochain cycle.
Exemple dans socket.js :


    // Handle errors from any source (HTTP client, stream, etc)
    var errorListener = function(e) {
        process.nextTick(function() {
            self.emit('wserror', e);

Le développeur reporte l'émission du signal d'erreur au cycvle suivant afin de laisser au programme appelant le temps d'installer les listeners.

ici d'autres exemples pour jouer avec l'instruction nextTick. Il est à noter que  l'instruction setTimeout avec une durée de 0 a le même effet.


Conseil 3: comprendre le fonctionnement de variables.
En javascript  c'est  au moment ou la variable est sollicitée que le contenu est fixé. Au déclenchement  d'un callback , il utilisera la valeur actuelle des variables. C'est pour ca qu'on trouve souvent des installation de callback sur le schéma suivant: appel immédiat à une fonction avec une variable  , cette fonction installera le callback avec la variable passée en paramètre

for(var i = 0; i < 5; i++) {
 (function(i) {
  setTimeout(function() {console.log('st2:'+i)}, 0);
 })(i);
}
Resulting in 0, 1, 2, 3, 4.

1 commentaire:

pixelmixture a dit…
Ce commentaire a été supprimé par un administrateur du blog.