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 :

Asynchrone > Ordonancement et contexte : je suis perdu


Sujet :

JavaScript

  1. #1
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut Asynchrone > Ordonancement et contexte : je suis perdu
    Bonjour,

    J'ai découvert JavaScript fin 90, et à l'époque, c'était tout simple : séquentiel, tout va bien.

    Seulement maintenant, tout est asynchrone, et en l'absence de formation / personne qui maîtrise sous la main, je galère un max pour ordonnancer mes actions et retrouver le contexte de fonctionnement.

    Je vais donc vous donner un exemple de ce que je veux faire en synchrone, et j'espère que vous saurez m'indiquer comment faire la même chose en asynchrone.

    Mettons donc un framework qui permet de faire du CRUD dans une table.

    Mettons que je dois augmenter le salaire de tous les cadres d'une société si celle-ci a fait du bénéfice.

    Ca va donc donner, en algo, un truc du genre :
    Création d'une variable "Augmentation" égale 0.
    Je recherche les infos de la société à partir de son ID.
    Si BENEFICE > 0, alors je fais rechercher l'ensemble des salariés de la société.
    Pour chaque salarié, si un CONTRAT = "Cadre", alors je charge son salaire, y additionne 10%, et incrémente aussi la variable "Augmentation" des 10%.
    Je retourne la variable "Augmentation".

    Code javascript : 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
     
    function AugmentationCadres(idSociete, pourcent)
    {
        var augmentation = 0;
     
        var infoSociete = CRUD.Load({ Table: "SOCIETE", Id: idSociete });
        if (infoSociete != null && infoSociete.BENEFICE > 0) {
            var listeSalaries = CRUD.LoadList({ Table: "SALARIE", Where: "soc_id = " + infoSociete.ID.ToString() });
            for (i = 0; i < listeSalaries.Count; i++) {
                var infoSalarie = CRUD.Load({ Table: "SALARIE", Id: listeSalaries[i].Id });
                if (infoSalarie != null && infoSalarie.CONTRAT == 'Cadre') {
                    var aug = infoSalarie.SALAIRE * pourcent;
                    augmentation += aug;
                    infoSalarie.SALAIRE += aug;
                    CRUD.Update({ Table: "SALAIRE", Record: infoSalarie });
                }
            }
        }
     
        return augmentation;
    }

    Youpi tralala, tout le monde est content (aux détails d'erreur de syntaxe).

    Maintenant, pas de pot, tout mon framework est asynchrone, chaque méthode de CRUD attends un callback.
    Comment faire ?

    Code javascript : 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
     
    function AugmentationCadres(idSociete, pourcent)
    {
        var augmentation = 0;
     
        // Comment je passe mon pourcentage à ma société ?
        CRUD.Load({ Table: "SOCIETE", Id: idSociete }, societeChargee);
     
        // Renvoie toujours 0
        return augmentation;
    }
     
    function societeChargee(res)
    {
        if (res != null && res.BENEFICE > 0) {
            CRUD.LoadList({ Table: "SALARIE", Where: "soc_id = " + res.ID.ToString() }, listeSalariesChargee);
        }
    }
     
    function listeSalariesChargee(res)
    {
        for (i = 0; i < res.Count; i++) {
            CRUD.Load({ Table: "SALARIE", Id: listeSalaries[i].Id }, salarieCharge);
        }
    }
     
    function salarieCharge(res)
    {
        if (res != null && res.CONTRAT == 'Cadre') {
            var aug = infoSalarie.SALAIRE * pourcent; // Comment je récupère mon poucentage ?
            augmentation += aug; // Comment je propage ma variable ?
            infoSalarie.SALAIRE += aug;
            CRUD.Update({ Table: "SALAIRE", Record: infoSalarie }, null);
        }
    }
    On ne jouit bien que de ce qu’on partage.

  2. #2
    Expert éminent sénior
    Avatar de Marco46
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2005
    Messages : 4 413
    Points : 19 609
    Points
    19 609
    Par défaut
    Il te faut utiliser un système de promesses.

    Le grand classique en la matière.
    Un problème avec Git ? Essayez la FAQ, sinon posez votre question sur le forum.



    "Toute personne croyant qu'une croissance exponentielle peut durer indéfiniment dans un monde fini est soit un fou, soit un économiste."
    Kenneth E. Boulding

    "Les richesses naturelles sont inépuisables, car, sans cela, nous ne les obtiendrions pas gratuitement. Ne pouvant être ni multipliées ni épuisées, elles ne sont pas l’objet des sciences économiques."
    Jean-Baptiste Say, Traité d'économie politique, 1803.

    "/home/earth is 102% full ... please delete anyone you can."
    Inconnu

  3. #3
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Outre le fait que j'ai absolument rien compris à vos promesses, j'avoue que j'ai pas du tout vu de lien avec mon problème

    (accessoirement, je ne pense pas pouvoir utiliser cette librairie : mon code javascript est chargé à la volée depuis une application existante, et je ne pense pas avoir le moyen d'ajouter des références à des scripts externes : j'ai pas la main sur les balises <script> de la page).
    On ne jouit bien que de ce qu’on partage.

  4. #4
    Expert éminent sénior
    Avatar de Marco46
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2005
    Messages : 4 413
    Points : 19 609
    Points
    19 609
    Par défaut
    j'avoue que j'ai pas du tout vu de lien avec mon problème
    Ben :

    Maintenant, pas de pot, tout mon framework est asynchrone, chaque méthode de CRUD attends un callback.
    Comment faire ?
    Le système de promesse te sert à synchroniser ce qui est asynchrone. Je peux pas t'expliquer ici comment ça fonctionne ça reviendrait à écrire un tutoriel.

    (accessoirement, je ne pense pas pouvoir utiliser cette librairie : mon code javascript est chargé à la volée depuis une application existante, et je ne pense pas avoir le moyen d'ajouter des références à des scripts externes : j'ai pas la main sur les balises <script> de la page).
    Bah si t'as pas la main sur le code je vois mal comment tu vas pouvoir faire quoi que ce soit !

    Je comprends pas trop là ...
    Un problème avec Git ? Essayez la FAQ, sinon posez votre question sur le forum.



    "Toute personne croyant qu'une croissance exponentielle peut durer indéfiniment dans un monde fini est soit un fou, soit un économiste."
    Kenneth E. Boulding

    "Les richesses naturelles sont inépuisables, car, sans cela, nous ne les obtiendrions pas gratuitement. Ne pouvant être ni multipliées ni épuisées, elles ne sont pas l’objet des sciences économiques."
    Jean-Baptiste Say, Traité d'économie politique, 1803.

    "/home/earth is 102% full ... please delete anyone you can."
    Inconnu

  5. #5
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Je peux créer des fichiers *.js

    Ils doivent être déclérés d'une certainement manière, et à ce moment, le programme sur lequel je travaille intègre mes js aux fichiers standard et expose mes classes à l'application.

    Mais je n'ai pas du tout la main sur l'application elle-même pour inclure d'autres scripts.

    En gros, voici un script que j'ai écrit hier :

    Fichier JSON qui va me permettre de charger mon script :

    cu.module.json
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    {
    	"dependsOn": ["base"],
    	"types": {
    		"CU": {
    			"scripts": [ "cu/cu.js" ]
    		},
    		"PriorityReader" : {
    			"scripts": [ "cu/priorityreader.js" ],
    			"dependsOn": [ "CU" ]
    		}
    	}
    }


    Scirpt de mon namespace cu.js :
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    (function () {
     
    	/*
    	    "u8.CU" is a namespace and namespaces must not contain functions, just types!
    	*/
     
    	u8.CU = {
    		// create the root namespace for all CU template types
    	};
     
    	$.extend(u8.CU, {
     
    	}); 
    })();

    Fichier contenant ma fonction que j'ai passé une journée à écrire et qui fait que le quart du boulot :
    Code javascript : 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
     
    (function () {
        u8.CU.PriorityReader =
    	{
    		Read: function(e)
    		{
    			u8.services.crud.readLink({ uid: e.uid, linkName: "$Link[MA]" }, this.NavigateTo);
    			u8.services.crud.update({ uid: e.uid, fields: [{ field: "F7024", value: "Y" }] }, function(sender, args)
    			{
    					if (args.businessObject)
    					{
    						console.info("PriorityReader set to \"read\".");
    					}
    					else
    					{
    						console.log("Error while updating PriorityReader!");
    						console.dir(args.businessObject);
    					}
    			});			
    		},
     
    		NavigateTo: function(sender, args)
    		{
    			if (args.businessObject)
    			{
    				console.info("Navigate to linked MA.");
    				/*u8.services.navigation.navigateToPage("Tree", { uid: args.businessObject.uid, createNewTab: true, viewMode: "Edit", onProceed: "$back" });*/
    				u8.services.navigation.navigateToPage("Process", { name: "TE_OpenRecordInCompanyTreeview", uid: args.businessObject.uid, createNewTab: true });
    			}
    			else
    			{
    				console.log("This PriorityReader isn't linked to a MA!");
    				console.dir(args);
    			}
    		}
        };
    })();

    Donc j'ai aucune moyen de faire un include du script que tu me soumets. Je dois me démerder avec les moyens du bord.
    On ne jouit bien que de ce qu’on partage.

  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
    Points : 9 944
    Points
    9 944
    Par défaut
    Il faudrait voir comment est codée cette bibliothèque de fonctions CRUD. Il y a plusieurs façons de gérer du code asynchrone, dont les deux plus connues sont les callbacks et les Promise.

    Les callbacks sont un argument supplémentaire de type fonction à passer aux fonctions asynchrones, généralement en dernier argument. Cette fonction est appelée quand l'API a fini son boulot asynchrone :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        CRUD.Load({ Table: "SOCIETE", Id: idSociete },  appelleMoiQuandTuAsFiniAvecMaValeur);
     
    function appelleMoiQuandTuAsFiniAvecMaValeur(societeChargee){
          console.log(societeChargee)
    }
    Les callbacks sont simples mais deviennent rapidement pénibles à gérer quand on fait plusieurs opérations asynchrones d'affilée. Cela amène à passer des fonctions à des fonctions à des fonctions, jusqu'à former des pyramides de code illisibles: http://callbackhell.com/

    On a donc inventé les Promise pour éviter ça. A la base, c'était des bibliothèques, aujourd'hui ça fait partie du standard ECMAScript 2015 et tous les navigateurs modernes ont l'API Promise.
    Les Promise, c'est un style d'API chaînable pour les opérations asynchrones. Un peu comme on chaîne les méthodes avec jQuery, on peut chaîner des opérations asynchrones "programmées", qui promettent de retourner une réponse ou une erreur dans un certain délai.
    Bref, c'est une manière plus élégante de coder en asynchrone, et je t'invite à te renseigner davantage sur le sujet. Parce que les Promise et la prog fonctionnelle, c'est cool

    A noter que l'instruction return ne sert à rien pour les fonctions asynchrones (puisque le cycle d'exécution de la fonction JS se termine en quelques millisecondes alors qu'une requête BDD ou autre opération asynchrone peut prendre bien plus longtemps). Pour la même raison, on ne peut pas transformer quelque-chose d'asynchrone en synchrone: à partir du moment où une fonction est asynchrone, toutes les fonctions appelantes le seront également ! Ça changera bientôt avec la norme ECMAScript 2016 et les mots-clés async/await (pour le meilleur et pour le pire).
    One Web to rule them all

  7. #7
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    il y a la gestion événementielle qui là aussi réponds au problème.

    les lib la mettant en oeuvre repose sur les callbacks
    à chaque action asynchrone lorsqu'on invoque l'action la lib fait l'appel et place une calback générique qui consiste à émettre un ou plusieurs événements.

    du coup on ne gère plus de calback mais on s'abonne à des événements.
    la différence c'est que la calback est lié à l'appel et est unique (un appel une calback) alors que l'événement est lié à un objet (window par exemple) et peut avoir autant d'abonné que l'on veut.

    A+JYT

  8. #8
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Points : 22 933
    Points
    22 933
    Billets dans le blog
    125
    Par défaut
    Citation Envoyé par SylvainPV Voir le message
    [...] Pour la même raison, on ne peut pas transformer quelque-chose d'asynchrone en synchrone: à partir du moment où une fonction est asynchrone, toutes les fonctions appelantes le seront également ! Ça changera bientôt avec la norme ECMAScript 2016 et les mots-clés async/await (pour le meilleur et pour le pire).
    Information : async/await est arrivé à l'étape 4 et sera normalement inclus dans ES2017

    Blog

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  9. #9
    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
    Points : 9 944
    Points
    9 944
    Par défaut
    Ah oui, c'est vrai que ES2016 ne contient presque rien et qu'ils ont repoussé ça à ES2017. Je m'y perds avec leurs numéros..
    One Web to rule them all

Discussions similaires

  1. [ODBC] Je suis perdu avec ODBC
    Par Nowhere dans le forum PHP & Base de données
    Réponses: 11
    Dernier message: 19/05/2006, 08h50
  2. [Tableaux] aide je suis perdu
    Par covin85 dans le forum Langage
    Réponses: 12
    Dernier message: 14/04/2006, 17h56
  3. [Architecture] EJB ou pas EJB ? Je suis perdu ...
    Par n!co dans le forum Java EE
    Réponses: 18
    Dernier message: 26/01/2006, 18h21
  4. RAM DDR, PC3200, 333Mhz , 400Mhz je suis perdu
    Par ahage4x4 dans le forum Composants
    Réponses: 2
    Dernier message: 08/12/2005, 17h52
  5. DLL et MainForm je suis perdu !
    Par rudy2 dans le forum C++Builder
    Réponses: 28
    Dernier message: 02/01/2005, 18h08

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