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

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Création librairie avec des callback


Sujet :

JavaScript

  1. #1
    Membre éprouvé
    Avatar de topolino
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    1 901
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 901
    Par défaut Création librairie avec des callback
    Bonjour,

    Je dois faire une libraire Javascript avec laquelle je dois me connecter à un serveur de push et faire des requetes qui enverrons des reponses de facons asynchrones.
    Si je devais le faire en c# j'aurais utilisé les evenements.

    Mais en Javascript je suis un peu perdu entre les callbacks, les promises et les events.

    J'ai compris que les promises seraient tres bien mais pas supportées par tous les navigateurs.


    Quel est votre avis ? Le top serait d'avoir un petit exemple pour que je puisse comparer les differente solutions.

    Merci à vous

  2. #2
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Par défaut
    En fait les promises et le pattern Observer (ce dont je pense tu fais référence par "events") ne sont que des API construites par-dessus la notion de callback. Et un callback, c'est tout simplement une fonction passée en argument et appelée suite à un traitement asynchrone. Il s'agit donc surtout d'une différence de syntaxe plus que de fonctionnement.

    Les promesses ont l'avantage d'être chaînables et d'éviter le "callback hell", qui consiste à imbriquer des fonctions dans des fonctions dans des fonctions jusqu'à se retrouver avec une pyramide de code difficilement maintenable. Aussi, en cas d'erreur elles transportent l'erreur jusqu'à la fin de la chaîne de traitements asynchrones, ce qui est pratique pour gérer toutes les erreurs au même endroit. Il y a bien une API standard Promise en ES6 qui est très peu supportée actuellement, mais d'autres librairies peuvent très bien simuler une API de type Promise. jQuery le fait notemment avec les Deferred. Donc ce n'est pas trop un problème de support.

    Je te conseille de commencer de manière simple avec des callbacks. Une fois que tu maîtriseras bien cette notion et que tu en auras vu les avantages/inconvénients, tu pourras t'intéresser aux Promise et voir ce que ça apporte.

  3. #3
    Membre éprouvé
    Avatar de topolino
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    1 901
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 901
    Par défaut
    Merci pour ta reponse. Je me suis appuyé sur un tuto du site. J'ai voulu le mettre sur JSFiddler mais je n'y arrive pas. Sinon mon exemple fonctionne bien.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
        <h1>Demo</h1>
        <input type="button" id="btnStart" value="start" />
        <input type="button" id="btnStop" value="stop" />
    <hr>
    Result <div id="result"></div>
       <script>
     
        var display = function(data, data2){
          document.getElementById('result').innerHTML = data;
        }
     
            $.getById('btnStart').on('click',function(){
                $.getById('btnStart').start(display)
              });
     
            $.getById('btnStop').on('click',function(){
                $.getById('btnStop').stop()
              });
       </script>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    (function(){      
    	var x;
        var myFWK = {
        	elems:[],
        	getById:function(){
            	var tempElems = [];
            	for(var i = 0; i<arguments.length; i++){
                	if(typeof arguments[i] === 'string'){
                    	tempElems.push(document.getElementById(arguments[i]));
                	}
            	}
            	this.elems = tempElems;
            	return this;
        	},
     
        	on: function(action, callback){
            	if(this.elems[0].addEventListener){
                	for(var i = 0;i<this.elems.length;i++){
                    	this.elems[i].addEventListener(action,callback,false);
                	}
            	}else if(this.elems[0].attachEvent){
                	for(var i = 0;i<this.elems.length;i++){
                    	this.elems[i].attachEvent('on'+action,callback); 
                	}
            	}
            	return this; // Renvoie this dans l'ordre d'appel
        	},
     
        	start:function(callback){
            	x = setInterval(function(){
                    var second = new Date().getSeconds();
                    callback(second,'non')
                }, 1000);
            	return this;
        	},
     
        	stop:function(){
            	clearInterval(x);
            	console.log('stop');
            	return this;
        	}        
    	}
     
    	if(!window.$){window.$=myFWK;}
    })();
    Les callbacks fonctionnent bien. Pour implementer les promises comment dois je faire ? inclure la librairie q ?

  4. #4
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Par défaut
    Tu risques d'avoir des problèmes à stocker les éléments sélectionnés directement sous l'objet myFWK. Question bête, pourquoi se lancer dans cette entreprise ? Auto-formation ? Un jQuery ou un Zepto ferait parfaitement l'affaire.

    Enfin pour répondre à ta question, si tu veux une interface de type Promise effectivement il te faut choisir une implémentation. Q en est une, il y en a bien d'autres: Bluebird, when.js, then.js...

  5. #5
    Membre éprouvé
    Avatar de topolino
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    1 901
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 901
    Par défaut
    Nous avons une application financiere KnockOut avec un serveur de push Nodes.
    Nous voulons donner à nos client la possibilité de se connecter diretement à notre web serveur pour avoir que les données.

    Pour des questions de securité, best practices... nous voulons leur donner une lib Javascript qui leur mache entierement le travail (connection, cache, transformation des données.....) et qui ne soit pas dependante d'un framework.

    La lib devra etre utilisable dans n'importe quels frameworks ou tout simplement en Javascript pur. Je cherche à comprendre comment creer de facon correct cette librairie

    Tu risques d'avoir des problèmes à stocker les éléments sélectionnés directement sous l'objet myFWK.
    Peux tu precisier.

    J'essaye de comprendre cette lib: https://github.com/andrew8088/dome/b...c/dome.js#L163
    Pourquoi au debut il utilise les prototypes puis à la fin un objet literal ?

  6. #6
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Par défaut
    Je pense que tu devrais séparer les fonctions génériques du style getById du reste de ton code propre au "métier". Un Zepto pèse moins de 10 Ko, on ne peut pas vraiment parler de framework. Il s'agit plus de libs utilitaires, histoire d'éviter de réinventer la roue. Aussi, s'approprier la variable globale $ n'est pas la meilleure façon de s'assurer d'être compatible avec n'importe quel framework.


    Tu risques d'avoir des problèmes à stocker les éléments sélectionnés directement sous l'objet myFWK.
    Imaginons que tu fais un traitement asynchrone comme une requête. Au callback, les éléments stockés dans myFWK peuvent avoir été modifiés par un autre appel. Référence commune = usage synchrone ou rien ; c'est pour ça que dans la lib dome il stocke les éléments en variables locales, comme ça elles sont indépendantes à chaque appel

    Regarde la différence entre messageArgument et Notif.message dans le code ci-dessous:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var Notif = {  
      message: null,
      show: function(messageArgument){
        Notif.message = messageArgument;
        setTimeout(function(){
          alert(messageArgument+ "/" + Notif.message)
        }, 1000)
      }
    }
     
    Notif.show("test1");
    Notif.show("test2");
    Pourquoi au debut il utilise les prototypes puis à la fin un objet literal ?


    Dome est son constructeur interne, sa "classe" si tu préfère. Elle n'est pas exposée globalement. dome en minuscule est son namespace global, celui exposé à l'utilisateur lui permettent d'utiliser la lib. L'un est une fonction constructeur, l'autre un objet jouant le rôle d'API.

  7. #7
    Membre éprouvé
    Avatar de topolino
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    1 901
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 901
    Par défaut
    Je pense que tu devrais séparer les fonctions génériques du style getById du reste de ton code propre au "métier". Un Zepto pèse moins de 10 Ko, on ne peut pas vraiment parler de framework. Il s'agit plus de libs utilitaires, histoire d'éviter de réinventer la roue. Aussi, s'approprier la variable globale $ n'est pas la meilleure façon de s'assurer d'être compatible avec n'importe quel framework.
    D'accord avec toi pour les separer, mais dois je faire 2 librairies separées alors ? et comment l'une peut inclure l'autre ?
    concernant globale $ --> D'accord avec toi, c'etait pour l'exemple.

    La librairie que je dois faire n'agit jamais sur le DOM, c'est juste une librairie pour appeler des fonctions afin de recevoir des données brut en asynchrones. Donc le faite d'utilisé un singleton (object literal ne me semble pas totalement faux.)

    Pour ton exemple de code, il s'agit des closures n'est ce pas ?: https://repl.it/BZ8Y

    Merci encore pour tes explications. J'apprecie

  8. #8
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Par défaut
    Toutes les fonctions créent des fermetures (closures), mais oui on emploie souvent le mot pour parler d'une fonction déclarée à l'intérieur d'une autre fonction. Plus d'infos ici : http://javascript.developpez.com/act...es-fermetures/

    A noter que ton namespace peut aussi être une fonction, comme c'est le cas pour jQuery avec $ et $.fn. Les fonctions sont des objets en JS.

    Pour la séparation, à toi de voir... si ta lib n'est pas censée agir sur le DOM, peut-être qu'il vaut mieux laisser le soin aux utilisateur de venir sélectionner les éléments de la manière dont ils préfèrent, avant de les balancer aux méthodes de ta lib.

  9. #9
    Membre éprouvé
    Avatar de topolino
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    1 901
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 901
    Par défaut
    Je commence à comprendre.
    Dans le cadre d'une librairie qui manipule le DOM, il est normal de travailler avec plusieurs instances de la librairie afin que chaque élément du DOM ne soit pas impacté par les autres.
    Comme dans mon cas, c'est juste une librairie pour faire des requêtes spécifiques sur le serveur et de recevoir des callback/data je peux simplement me satisfaire d'un objet literal, car les méthodes n'impactent pas les autres méthodes de la librairie ni le DOM (Elles sont indépendantes des unes des autres).

    Suis dans le bon raisonnement ? ou je melange encore tout ?

    Merci

  10. #10
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Par défaut
    "instance de la lib" c'est pas le bon mot. Qui dit instance dit constructeur. Ta bibliothèque peut utiliser un ou plusieurs constructeurs en interne, ou pas du tout, selon le style du développeur. Perso je n'en utilise pas du tout. Il n'y a pas de recette toute faite pour écrire une bibliothèque, chacun fait un peu comme il l'entend. L'important c'est de ne pas exposer trop de variables globales et d'exposer une API simple pour l'utilisateur. Des API on en voit de tous les styles, ça peut être un simple objet littéral comme ça peut être un greffon à un élément existant, ou un constructeur...

    Les méthodes n'ont pas à être indépendantes les unes des autres, c'est totalement sensé de vouloir faire appel à une méthode dans une autre méthode, c'est comme ça qu'on fonctionnalise son code. Je crois que l'exemple de la référence unique t'a embrouillé plus qu'autre chose. Le problème, c'est pas d'impacter le DOM ou non, c'est de s'assurer de ne pas avoir de références croisées.

    1) J'appelle ma lib avec l'élément A, je mets l'élément A dans une prop de l'objet maLib, maLib.stockage = A ; puis je fais un traitement asynchrone (requête) qui va répondre 1 seconde plus tard
    2) Juste derrière j'appelle ma lib avec l'élément B, je mets l'élément B dans la même prop de l"objet maLib, maLib.stockage = B
    3) quand la première requête répond, je veux récupérer mon élément dans maLib.stockage, mais là où je m'attends à trouver A, je tombe sur B !

    Dans ce cas, ce qui doit être indépendant, c'est le contexte d'appel de la méthode ta lib. Autrement dit, les arguments. Les arguments sont des variables locales, donc aucun risque de conflit. C'est plus clair ?

  11. #11
    Membre éprouvé
    Avatar de topolino
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    1 901
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 901
    Par défaut
    Oui c'est beaucoup plus clair.

    Merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 21/07/2009, 12h00
  2. Réponses: 4
    Dernier message: 15/10/2007, 18h56
  3. [JAR]Création d'un JAR avec des dependances sous Eclipse
    Par muthnik dans le forum Eclipse Java
    Réponses: 4
    Dernier message: 05/07/2005, 17h39
  4. Réponses: 3
    Dernier message: 25/01/2005, 11h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo