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 :

Rendre synchrone une fonction asynchrone


Sujet :

JavaScript

  1. #1
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 197
    Billets dans le blog
    1
    Par défaut Rendre synchrone une fonction asynchrone
    Bonjour,

    Je travaille sur un outil (Aurea.CRM) que je peux enrichir avec mes propres scripts JavaScript.

    Cet outil dispose d'un outil d'administration qui permet, par exemple sur un bouton, de piloter certaines de ses propriétés en appelant des fonctions JavaScript.

    J'ai donc un bouton, que je souhaite rendre visible ou non selon les droits de l'utilisateur.



    Comme vous le voyez, j'ai pas la main sur grand chose, c'est un appel synchrone à une fonction, qui va me retourner un objet indiquant si l'objet est visible et/ou grisé.

    J'ai donc écrit une fonction JavaScript, reposant sur le Framework de l'outils :

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Test: function(e) {
    	var res;
     
    	u8.services.schema.getConditionalRights({uid: e.parent.link, options: {flags:"CheckUpdateRight"}},
    		function(o) {
    			res = (o._rights.length === 0);
    		}
    	);
     
    	return {visible: res};
    }

    Seul hic, la méthode u8.services.schema.getConditionalRights() est asynchrone, et le call back s'exécute après que je sois sorti de la fonction Test().

    J'ai donc besoin de trouver un moyen de déclencher u8.services.schema.getConditionalRights(), attendre que le callback ait terminé, puis retourner ma variable res mise à jour.

    Comment faire ?
    J'ai essayé d'utiliser un Deferred/Promise mais sans succès, async/await sans plus de succès... Je ne sais pas du tout comment faire tomber le truc en marche

  2. #2
    Expert confirmé Avatar de Toufik83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    2 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 2 496
    Par défaut
    Bonjour,

    Je pense que tu peux le faire sans promesse si tu n'obliges pas la fonction Test() de retourner quelque chose, parce que la fonction function(o){...} est déjà le callback de l'appelle asynchrone, et elle s'exécute à l'instant où les données soient disponibles, donc sans promesse donne ceci :
    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
     
    var obj = {
      Test: function(e) {
         u8.services.schema.getConditionalRights({
                uid: e.parent.link,
                options: {
                  flags: "CheckUpdateRight"
                }
          },
          function(o) {//cette fonction est le callback de u8.services.....
            console.log("data is :", o);
    	if(o._rights.length==0){/* code pour true*/}
            else{/* code pour false */}
         });
      }
    }
    //appelle à Test() cette fois sans then sans rien :
    obj.Test();
    Sinon et si tu veux qu'elle retourne un objet {visible:true/false}, il va falloir l'écrire et l'appeler comme suite :
    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
     
    var obj = {
      Test: function(e) {
        return new Promise((resolve, reject) => {
           u8.services.schema.getConditionalRights({
              uid: e.parent.link,
              options: {
                flags: "CheckUpdateRight"
              }
            },
            function(o) {
              return resolve({
                visible: o._rights.length === 0
              });
            });
        });
      }
    }
     
    //appel à la fonction Test Obligatoire avec then :
    obj.Test().then((o) => { 
      console.log("data is :", o);
      if (o.visible) {
        //code pour visible==true
      } else {
        //code pour visible==false
      }
    });

  3. #3
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 197
    Billets dans le blog
    1
    Par défaut
    Merci Toufik

    Ca ressemble vachement à ce que j'avais testé.

    Je regarde ça et je te tiens au courant

  4. #4
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 197
    Billets dans le blog
    1
    Par défaut
    Bonjour, et désolé pour le délai de réponse...

    Je viens de retester tout ça, et je ne m'explique absolument pas ce qu'il se passe :

    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
     
    		_innerQueryStateC009: function(e) {
    			return new Promise((resolve, reject) => {
    				u8.services.schema.getConditionalRights({
    					uid: e.parent.link,
    					options: {
    						flags: "CheckUpdateRight"
    					}
    				},
    				function(o) {
    					return resolve({
    						visible: o._rights.length === 0,
    						done: o._rights.length === 0
    					});
    				});
    			});
    		},
    		QueryStateC009: function(e) {
    			var res = null; /*{
    						visible: false,
    						done: false
    					};*/
    			u8.Custom.Affaire._innerQueryStateC009(e).then((o) => {
    				res = o;
    			});
    			console.log("data is :", res);
    			return res;
    		}

    Si j'appelle QueryStateC009() j'ai ça comme sortie :
    data is :{visible: false, done: false}

    En revanche, le programme appelant ne traite pas correctement le retour de la fonction, car mon bouton reste visible.

    Si je modifie comme suit :
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    		QueryStateC009: function(e) {
    			var res = {
    						visible: false,
    						done: false
    					};
    			//u8.Custom.Affaire._innerQueryStateC009(e).then((o) => {
    			/	res = o;
    			//});
    			console.log("data is :", res);
    			return res;
    		}

    Cette fois, ça fonctionne normalement, mon bouton disparaît !

    Que faire ???

  5. #5
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 197
    Billets dans le blog
    1
    Par défaut
    J'y comprend rien, c'est complètement incohérent...

    Ca tourne toujours de manière asynchrone :
    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
     
    		_innerQueryStateC009: function(e) {
    			return new Promise((resolve, reject) => {
    				u8.services.schema.getConditionalRights({
    					uid: e.parent.link,
    					options: {
    						flags: "CheckUpdateRight"
    					}
    				},
    				function(o) {
    					return resolve(o._rights.length === 0);
    				});
    			});
    		},
    		QueryStateC009: function(e) {
    			var res = null;
    			u8.Custom.Affaire._innerQueryStateC009(e).then((o) => {
    				console.log("o = :", o);
    				res = o;
    			});
    			console.log("data is :", res);
    			return {visible: res, done: res};
    		}

    Ca fait ça dans le debugger :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    data is : null
    o = : false
    Donc le then() s'exécute bien après les lignes situées après l'appel à ma fonction _innerQueryStateC009

    Le truc incompréhensible, c'est que dans mon post précédent, le debugger indiquant pourtant que le then() s'exécutait avant, contrairement au comportement constaté

  6. #6
    Expert confirmé Avatar de Toufik83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    2 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 2 496
    Par défaut
    Bonjour,

    ça te renvoi null car tu mets le console.log à l'extérieur de then, et javascript n'attendra pas le retour de "u8.Custom" et passe directement aux lignes suivantes.

    Il faut mettre toutes les instructions relatives à l'intérieur de then, puis un return avant "u8.Custom.Affaire_"
    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
     
    _innerQueryStateC009: function(e) {
    	return new Promise((resolve, reject) => {
    		u8.services.schema.getConditionalRights({
    			uid: e.parent.link,
    				options: {
    				flags: "CheckUpdateRight"
    			}
    		},
    		function(o) {
    			return resolve(o._rights.length === 0);
    		});
    	});
    },
    QueryStateC009: function(e) {
            var res = null;
            /* ajoutes un return avant u8.Custom.Affaire_*/
    	return u8.Custom.Affaire._innerQueryStateC009(e).then((o) => {
    		console.log("o = :", o);
    		res = o;
                    console.log("data is :", res);//que donne maintenant ce console ?
    	        return {visible: res, done: res};
    	});
    }
    Question : est-ce que tu es obligé de retourner les données avec return ? ou bien seulement exécuter des instructions js lors de la réception des données ?

  7. #7
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 197
    Billets dans le blog
    1
    Par défaut
    Je dois obligatoirement retourner des données avec return, c'est bien là le souci

  8. #8
    Expert confirmé Avatar de Toufik83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    2 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 2 496
    Par défaut
    Bonjour,

    L'un des principes fondamentaux d'une promesse est qu'elle est gérée de manière asynchrone. Cela signifie que vous ne pouvez pas créer une promesse puis utiliser immédiatement son résultat de manière synchrone dans votre code (par exemple, il n'est pas possible de renvoyer le résultat d'une promesse à partir de la fonction qui a initié la promesse).

    Ce que vous voudrez probablement faire à la place est de retourner la promesse elle-même, et n'importe quelle fonction a besoin de son résultat elle doit obligatoirement faire appel à then() afin de récupérer le retour de la promesse , et le résultat sera là lorsque la promesse aura été (soit résolue, soit rejetée).

  9. #9
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 197
    Billets dans le blog
    1
    Par défaut
    Vu comme c'est parti, j'ai bien l'impression que c'est râpé quoi

    Merci pour ton aide !

Discussions similaires

  1. Ratchet & ReactPHP: Créer une fonction asynchrone
    Par n0wis dans le forum Bibliothèques et frameworks
    Réponses: 0
    Dernier message: 16/11/2015, 11h47
  2. Attendre la fin d'une fonction asynchrone
    Par JustyDark dans le forum NodeJS
    Réponses: 6
    Dernier message: 18/05/2015, 23h11
  3. Rendre générique une fonction d'ouverture de formulaire
    Par clickandgo dans le forum VBA Access
    Réponses: 5
    Dernier message: 30/01/2015, 12h03
  4. Rendre Asynchrone une fonction
    Par contender dans le forum C#
    Réponses: 3
    Dernier message: 18/06/2012, 12h11
  5. Savoir la fin d'execution d'une fonction asynchrone
    Par winnyzeboss1 dans le forum C++
    Réponses: 9
    Dernier message: 20/03/2009, 14h46

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