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 :

Promise et retour de fonctions anonymes


Sujet :

JavaScript

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    5
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2008
    Messages : 5
    Points : 5
    Points
    5
    Par défaut Promise et retour de fonctions anonymes
    Hello

    Je suis debutant en javascript et j’ai encore du mal avec la notion des promesses.
    Dans mon exemple ja’i deux fonctions, une pour recuperer des donnees patients et une autre pour recuperer ses conditions (diagnostics)

    bien sur le console.log dans les deux fonctions fonctionnent tres bien mais je ne ne recupere rien dans le return.
    Que dois je changer pour recuperer mon tableau de donnees datawiz en retour de la fonction getPatientConditions?

    Code HTML : 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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    <!DOCTYPE html> 
    <html>
    	<head>
    		<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/ >
    		<title>EyeC1</title>
    		<script src='http://code.jquery.com/jquery-2.1.4.min.js'></script>
            <script src='fhir-client.js'></script>
     
     
    	</head>
    	<body>
     
    		<div class="eyeChart"></div>
     
    		<script src="eyeChart.js"></script>
    		<script>
                // recuperer l'IPP depuis l'URL (contexte patient)
                
                var IPP = getUrlVars()["IPP"];
                var patient = {
                    serviceUrl: "https://r2.smarthealthit.org",
                    patientId: IPP,
                    auth: {
                        type: 'none'
                    }
                };
                
               
                
                getPatientData(patient);
                getPatientConditions(patient);
     
                
                
                //******************** Fonctions
                function getUrlVars() {
                    var vars = {};
                    var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
                        vars[key] = value;
                    });
                    return vars;
                }
                function getPatientData(patient){
     
                    var eyeDiagFHIR = FHIR.client(patient);
                    var monPatient = eyeDiagFHIR.patient.read();
                    var formatted="";
                    monPatient.then(function(p) {
                        var name = p.name[0]; // a ameliorer et recuperer un nom, prenom de type exact
                        var gender = p.gender;
                        var DN = p.birthDate;
                        var formatted = name.given.join(" ") + " " + name.family.join(" ");
                        console.log(formatted);
                    });
                    return formatted;
                }
                function getPatientConditions(patient){
                    var eyeDiagFHIR = FHIR.client(patient);
                    //  reccuperer les conditions du patient
                    var datawiz=[];
                    // call the function
                    //function getConditions(IPP)
                    eyeDiagFHIR.patient.api.search({type: 'Condition'}).then(function(results){  
                        // boucler sur le tableau des conditions
                        results.data.entry.forEach(function(condition){
                            diagDate = condition.resource.onsetDateTime;
                            // il est possible d'avoir plusieurs codes pour le meme diag (on considere qu'il y en a 1 seul)
                            condition.resource.code.coding.forEach(function(codes){  
                                diagnostic = codes.code;
                                const request = async () => {
                                    const urlSev = "https://bridge.buddyweb.fr/api/cim10snomedald/cim10nomenclature?cim_code="+codes.code;
                                    const response = await fetch(urlSev);
                                    const json = await response.json();
                                    total = json[0].cim_total;
                                    index = json[0].cim_index;
                                    cmd = json[0].cim_cmd;
                                    libelle = json[0].cim_libelle;
                                    severite = json[0].cim_niveau_de_severite;
                                    datawiz.push({axis:cmd,value:severite,date:diagDate,libelle:libelle,index:index,total:total});
                                    console.log(datawiz);
                                }
                                request();
                                return (datawiz);
                            }) 
                        })
                    });     
                }
                    </script>
    	</body>
    </html>

  2. #2
    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


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var patientData = getPatientData(patient);
    var patientConditions = getPatientConditions(patient);

    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.)

  3. #3
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    Bonsoir !
    Dans ta fonction getPatientConditions, tu déclares une fonction request qui est asynchrone. Ainsi, quand ton code appelle request(), le traitement du code de request après le premier await est « remis à plus tard » et l’exécution se poursuit immédiatement avec l’instruction suivante, le return.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    getPatientConditions/forEach                      | temps
    ----------------------------                      v
             |
             | …
             |
             x déclaration de async request
             |
             x appel request() --> await ---.
             |                              |
             x return                       |
                                            v
                                            plus tard
    Dans le monde de JavaScript, « plus tard » ça veut dire dès que le fil d’exécution est libre. Et comme JS n’a qu’un seul fil d’exécution (si on ne parle pas des workers), ça veut dire au moins attendre que la pile d’appels soit à nouveau vide. La doc Concurrence et boucle des évènements pourrait t’aider à comprendre un peu mieux ces histoires.

    Pour remettre les choses dans l’ordre, il faudrait que le return « attende » la fin de request, donc il faudrait rendre la fonction forEach englobante asynchrone elle aussi. Mais cette forEach justement, parlons-en : l’instruction return se trouve dedans. Or, un return dans une forEach ça ne sert à rien. Je pense que tu as un problème de conception ici.

    Prenons un peu de recul et regardons ce qui se passe lors des itérations forEach successives.
    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
    getPatientConditions                              | temps
    --------------------                              v
           |
           | …
           |
           x forEach
           |    |
           |    +--- function (codes) {
           |    |      |
           |    |      x appel request() --> await -------> plus tard <1>
           |    |      |
           |    |      x return datawiz (non pris en compte)
           |    |
           |    |
           |    +--- function (codes) {
           |    |      |
           |    |      x appel request() --> await -------> plus tard <2>
           |    |      |
           |    |      x return datawiz (non pris en compte)
           |    |
           |    etc.
           |
           x return
    
    pile vide => les appels asynchrones sont exécutés maintenant
    
    request <1>
    -----------
        |
        | …
        |
    
    request <2>
    -----------
        |
        | …
        |
    
    etc.
    (En réalité c’est même encore plus compliqué que ça, car il y a plusieurs await dans la fonction request, et plusieurs blocs de code sont repoussés à plus tard successivement.)

    On voit bien que le return datawiz n’est pas au bon endroit, et que les traitements request sont faits trop tard.

    Dans la mesure où un traitement asynchrone se produit à l’intérieur de getPatientConditions, tu n’as pas d’autre choix que de rendre cette fonction asynchrone elle aussi. Donc :
    • soit tu la déclares async et tu mets des await dedans ;
    • soit tu lui fais retourner une promesse.

    … Ce qui revient au même, en fait.

    Pour commencer, il te faut un mécanisme pour déterminer quand tous les appels à request ont été faits. Comme tu as une structure à deux dimensions (il faut deux forEach imbriqués pour la parcourir), ça complique un peu les choses.
    Je pense que le plus simple est de créer un tableau à une seule dimension dans lequel on va placer des promesses qui indiqueront quand une fonction request a terminé. Puis nous utiliserons Promise.all qui nous permet d’attendre que toutes les promesses soient résolues.
    Le résultat de Promise.all est lui-même une promesse, tu peux la renvoyer directement dans un return. Ainsi, tu pourras appeler getPatientConditions(...).then(...).

    (Au passage, attention à cette variable diagnostic qui semble être accidentellement globale – je ne vois pas l’endroit où tu la déclares dans le code que tu as donné. Je te conseille d’utiliser le mode strict.)

    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
      ...
      const datawiz = [];
      const promises = [];
     
      eyeDiagFHIR.patient.api.search({ type: "Condition" }).then(function (results) {
        // boucler sur le tableau des conditions
        results.data.entry.forEach(function (condition) {
          ...
          condition.resource.code.coding.forEach(function (codes) {
            // on ajoute une promesse au tableau
            promises.push(new Promise((resolve, reject) => {
              const request = async () => {
                ...
                // à la fin de request, on résoud la promesse
                resolve();
              };
              request();
              // pas de return
            });
          });
        });
      });
     
      return Promise.all(promises);
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

Discussions similaires

  1. retour fonctions anonymes
    Par N3jidev dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 14/10/2010, 21h10
  2. [JS] Fonction anonyme et retour de variable ?
    Par lounislounis dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 25/07/2010, 00h23
  3. Retour de fonction en C
    Par troumad dans le forum Linux
    Réponses: 2
    Dernier message: 06/11/2005, 21h43
  4. Utilisation d'un retour de fonction dans un decode
    Par CFVince dans le forum Oracle
    Réponses: 4
    Dernier message: 20/10/2005, 17h22
  5. Référence en retour de fonction, à transformer en hash
    Par raoulchatigre dans le forum Langage
    Réponses: 4
    Dernier message: 15/07/2005, 14h24

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