Discussion: Soucis avec Promise

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    mai 2007
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2007
    Messages : 22
    Points : 15
    Points
    15

    Par défaut Soucis avec Promise

    Bonjour à vous tous,
    Débutant en nodeJs, j'essayes de comprendre les Promises...
    Pourriez vous m'aider sur cette fonction : Les variables sont valides ("value[0]", "value[3]...[i]")
    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
     
    static RechCritUserById(value) {
    			return new Promise((resolve, reject) => {
     
    			for (var i = 0; i < value[3].length; i++) {
    				let ParId = value[3][i];
    				let UsrId = value[0];
    				console.log(' A : ', ParId)
    				var query_str = 'SELECT * FROM usr_par WHERE usr_id = ? AND par_id = ?';
    				var query_var = [UsrId, ParId];
    				connection.query(query_str, query_var, function (err, rows) {
    					if (err) {
    						return reject(err);
    					}
    					else {
    						if (rows.length != 0) {
    							console.log(' B ')
    							value.push(rows);
    						}
    						else {
    							console.log(' C ')
    							var trans = { up_id: '', usr_id: UsrId, par_id: ParId, up_val: 0 }
    							value.push(trans);
    						}
    					}
    				});
    			}
    			console.log(' D ')
    			resolve(value);
    		});
    	}
    Comme vous pouvez le voir j'ai place des "console.log" pour savoir ou j'en étais...
    Et comme résultat j'ai :

    A
    A
    A
    D
    B
    B
    C
    Le "D" qui est le "resolve" arrive trop tôt et donc "value" n'est pas incrémenté des nouvelles valeurs.
    Comment pourrais-je faire ?
    Merci de votre aise et temps.
    Acqua2b

  2. #2
    Membre expert Avatar de psychadelic
    Profil pro
    Inscrit en
    mai 2010
    Messages
    1 811
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2010
    Messages : 1 811
    Points : 3 633
    Points
    3 633

    Par défaut

    ton resolve est placé apres la boucle for(...

    donc c'est logique, dès que cette boucle est terminé il y va !

    cette boucle envoit plusieurs fois une fonction asynchrone ( connection.query ) dont chaque instance prendra son temps utile, et qui ont peut de chance de s'achever avant l'éxécution totale de la dite boucle.

    J'ai l'impression que tu n'a pas vraiment intégré ce qu'est la logique asynchrone...
    «La pluralité des voix n'est pas une preuve, pour les vérités malaisées à découvrir, tant il est bien plus vraisemblable qu'un homme seul les ait rencontrées que tout un peuple.» [ René Descartes ] - Discours de la méthode

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    mai 2007
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2007
    Messages : 22
    Points : 15
    Points
    15

    Par défaut

    Merci psychadelic de ta reponse.

    Effectivement je crois que j'ai besoin de me rafraichir la mémoire... Plus j'avance et moins je comprend...
    Asynchrone est non bloquant.
    Mais je pensais que la boucle "for" allait s'exécuter entièrement avant de sortir... et enfin résoudre (resolve)
    Je pensais faire du Sync.... Suis perdu !?
    Comment je peux faire pour parvenir à ce que je veux faire ?

    Merci de ton temps

  4. #4
    Membre expert Avatar de psychadelic
    Profil pro
    Inscrit en
    mai 2010
    Messages
    1 811
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2010
    Messages : 1 811
    Points : 3 633
    Points
    3 633

    Par défaut

    et qu'est-ce que tu veux faire alors ?
    parce que ton code n'explique rien. un minimum d'explication en Français est nécessaire.
    «La pluralité des voix n'est pas une preuve, pour les vérités malaisées à découvrir, tant il est bien plus vraisemblable qu'un homme seul les ait rencontrées que tout un peuple.» [ René Descartes ] - Discours de la méthode

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    mai 2007
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2007
    Messages : 22
    Points : 15
    Points
    15

    Par défaut

    Ok

    J'ai un tableau "value"qui contient des informations comme l'ID utilisateur courant (value[0])
    En "value[3]" il y a un tableau d'Identifiants de tous les paramètres présent dans ma table "parametres" de ma BDD.
    Je veux voir si tous ces paramètres sont renseignés pour l'utilisateur courant et les ajouter dans mon array (value)
    - si un paramètre n'est pas présent je l'ajoute dans "value[]" par défaut.

    Ensuite j'utilise "value[]" pour afficher les différentes informations dans ma page de vue (ejs)

    voila j'espère avoir été clair
    Merci

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    mai 2007
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2007
    Messages : 22
    Points : 15
    Points
    15

    Par défaut

    Je viens de faire d'une autre manière, en utilisant une boucle "while" et en supprimant "return new Promise" :

    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
     
    static RechParamsUserByIdParams(value) {
     
    			let tableau = [];
    			let i = 0;
     
    			while (i < value[3].length) {
    				let ParId = value[3][i];
    				let UsrId = value[0];
    				console.log(' A : ', ParId)
    				var query_str = 'SELECT * FROM usr_par WHERE usr_id = ? AND par_id = ?';
    				var query_var = [UsrId, ParId];
    				connection.query(query_str, query_var, function (err, rows) {
    					if (err) {
    						console.log('Err ')						
    						return reject(err);
    					}
    					else {
    						if (rows.length != 0) {
    							console.log(' B ')
    							console.log('ROWS : ', rows[0])
    							tableau.push(rows[0]);
    						}
    						else {
    							console.log(' C ')
    							var cree = { up_id: '', usr_id: UsrId, par_id: ParId, up_val: 0 }
    							console.log('CREE : ', cree)
    							tableau.push(cree);
    						}
    					}
     
    				});
    				i++;
    			}
    			console.log(' D ')
    			value.push(tableau);
    			// console.log('Resolve RechCritUserById', value)
    			return value;
     
    	}
    Il m'affiche toujours :
    A
    A
    A
    D
    B
    B
    C
    Je pensais : tant que "i" est inférieur à "lenght" ont restais dans la boucle "while" !?

  7. #7
    Membre expert Avatar de psychadelic
    Profil pro
    Inscrit en
    mai 2010
    Messages
    1 811
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2010
    Messages : 1 811
    Points : 3 633
    Points
    3 633

    Par défaut

    Citation Envoyé par acqua2b Voir le message
    Je pensais : tant que "i" est inférieur à "lenght" ont restais dans la boucle "while" !?
    non.
    Javascript est un langage qui permet d'utiliser des fonctions asynchrones.

    dans ta boucle tu appelle X fois ta fonction connection.query (cad dire la tache codée entre les lignes 13 à 32 dans ton dernier code) qui est justement une fonction asynchrone. c'est un peu comme ci elle lançait X taches à réaliser.

    la boucle ne s'occupe que de lancer ces taches les unes à la suite des autres, elle ne s'occupe pas de savoir si la précédente s'est entièrement déroulée avant d'envoyer la suivante, et une fois cette série de taches lancées, elle continue l'éxécution de son code présent à la suite de sa boucle.


    les promesses en javascript est une méthode pour utiliser de manière synchrone les fonctions asynchrones, c'est à dire que chaque tache à effectuer est encadrée par une promesse, genre
    " je te demande de réaliser cette tache et j'attends que tu la réalise pour continuer, et l'encadrement par une promesse se charge spécifiquement de la tache en question et regarde si elle s’exécute correctement ou non, car dans un cas de réussite comme d'échec, elle à promis d'en rendre compte au demandeur. c'est pour ça que ça s'appelle une promesse.
    «La pluralité des voix n'est pas une preuve, pour les vérités malaisées à découvrir, tant il est bien plus vraisemblable qu'un homme seul les ait rencontrées que tout un peuple.» [ René Descartes ] - Discours de la méthode

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    mai 2007
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2007
    Messages : 22
    Points : 15
    Points
    15

    Par défaut

    Merci psychadelic pour ton temps et explications.

    Je vais regarder la video.

    Merci

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    mai 2007
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2007
    Messages : 22
    Points : 15
    Points
    15

    Par défaut

    Au secours !

    Je n'y arrive pas... J'ai beau tourner le soucis dans tous les sens...
    Il y a cette boucle 'FOR" (ou "while") qui m'empêche de faire ce que je veux...
    Car comme javascript est "asynchrone" et ben il n'attend pas la fin de la boucle pour résoudre...

    Je ne sais pas comment faire ?

    psychadelic peux tu m'aider s'il te plait... merci

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    mai 2007
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2007
    Messages : 22
    Points : 15
    Points
    15

    Par défaut

    Bon j'ai trouvé cela :

    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
    47
     
    static RechParamsUserByIdParams(value) {
    		var promises = [];		
    		for (var i = 0; i < value[3].length; i++) 
    		{
    			let numb = value[3][i];
    			console.error('Valeur de Numb : ', numb)
    				promises.push(Users.checkValue(numb, value[0]));
    		}
     
    		Promise.all(promises)    
    		 .then(function(data){ 
    			  console.log('D A T A : ', data)
    				value.push(data);
    				return value;
     
    			}).catch((e) => { console.error(e); });
     
    	}
     
    	static checkValue(ParId, UsrId){
    		return new Promise(function(resolve, reject){
     
    			var query_str = 'SELECT * FROM usr_par WHERE usr_id = ? AND par_id = ?';
    			var query_var = [UsrId, ParId];
    			connection.query(query_str, query_var, function (err, rows) {
    				if (err) {
    					console.log(' E R R O R ')						
    					reject(err);
    				}
    				else {
    					if (rows.length != 0) {
    						console.log(' B ')
    						console.log('ROWS : ', rows[0])
    						resolve(rows[0]);
    					}
    					else {
    						console.log(' C ')
    						var cree = { up_id: '', usr_id: UsrId, par_id: ParId, up_val: 0 }
    						console.log('CREE : ', cree)
    						resolve(cree);
    					}
    				}
     
    			});
    		});
    	}
    Mais j'ai une erreur :
    (node:67662) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot read property '1' of undefined
    (node:67662) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    Sur internet ils parlent de ".catch" Absent ... Mais où ?
    Et je me demande si le :

    value.push(data); (Ligne 14).
    Fait son boulot ?
    Ajouter les valeur dans 'value' Je n'ai pas de retour !?

    Merci de votre aide

  11. #11
    Membre expert Avatar de psychadelic
    Profil pro
    Inscrit en
    mai 2010
    Messages
    1 811
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2010
    Messages : 1 811
    Points : 3 633
    Points
    3 633

    Par défaut

    Le problème, c'est que je ne suis pas suffisamment familiarisé avec NodeJS, et que je sais que les premières version NodeJS avaient fait des impasses sur l'utilisation des promesses.
    et donc je ne connais pas ta fonction connection.query dont je sais juste qu'elle est asynchrone, mais j'imagine qu"elle possède quelques subtilités.

    La première chose à comprendre sur ton code, c'est que dois gérer autant de promesses qu'il y a de fonctions asynchrone appelées.

    tu doit donc coder une boucle de promesses.

    L'autre difficulté de ton code, c'est que ces promesses doivent s’exécuter l'une après l'autre, car elles doivent remplir la même pile (ton tableau "value") , et qu'y faire des accès en concurrence pour ajouter des éléments est le meilleur moyen de tout planter.

    Au passage, appeler "value" un tableau c'est pas très malin, c'est aussi le meilleur moyen de se mettre des nœuds dans le cerveau car le mot "values" est un mot clé en JavaScript et restera toujours dans la tête de tous les informaticien un principe et non le nom d'une variable.
    Bref il faut lui donner un nom permettant de se faire une idée de ce à quoi sert une variable; par exemple Liste_Refs_Utilisateur.

    Bref, tu attaque la problématique des promesses par le moins simple pour commencer, et en utilisant des noms à la c**.


    Alors cas d'école:

    Petite fonction asynchrone et typique en JavaScript.
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        function f_DelaiPromise(tms, ref) {
          new Promise(function (resolve) {
            console.log('ref=' + ref);
            setTimeout(resolve, tms);
          });
        };

    c'est une fonction classique contenant une promesse dont le setTimeout en appelle le callBack résolve.

    En codant en ES6 ça donne const delay = ms => new Promise(resolve => setTimeout(resolve, ms));(sans le console.log) et je met ce code car si tu étudie les promesses tu risque de le rencontrer sous cette forme.


    En JS, la fonction qui appelle une ou plusieurs promesse à elle même l'obligation d'utiliser une syntaxe particulière, et comme JS ne fait pas les choses à moité il existe plusieurs écritures.
    Mais dans le cas qui t'intéresse il faut utiliser la méthode avec les async et await, (à cause de la boucle) qui sont bien plus simples à utiliser

    Ce qui donne :
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        async function boucle_10() {
          for (let i = 0; i < 10; i++) {
            await f_DelaiPromise((Math.random() * 1000), i);
            console.log("boucle=" + i);
          }
        };

    et qui s’appelle ensuite : par un simple boucle_10();
    maintenant tu n'a plus qu' remplacer la fonction f_DelaiPromise par ta propre fonction f_connection_query (contenant ton connection.query )

    ajouter la gestion d'erreur dans les await ( avec un try catch classique )
    «La pluralité des voix n'est pas une preuve, pour les vérités malaisées à découvrir, tant il est bien plus vraisemblable qu'un homme seul les ait rencontrées que tout un peuple.» [ René Descartes ] - Discours de la méthode

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    mai 2007
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2007
    Messages : 22
    Points : 15
    Points
    15

    Par défaut

    psychadelic,

    Merci pour ton explication.

    J'ai posté un nouveau code qui devrait fonctionner... mais j'ai des erreurs.
    Ce code devrait faire ce que je veux mais il y a un souci de "catch".
    Je vais essayer de me débrouiller...
    Merci pour tout.

  13. #13
    Membre actif Avatar de Altak
    Homme Profil pro
    Développeur informatique
    Inscrit en
    octobre 2014
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : octobre 2014
    Messages : 168
    Points : 240
    Points
    240

    Par défaut

    Hello,

    J'arrive un peu tard mais si tu as besoin d'aide, je suis la :p

    Tu as réussis à résoudre ton problème?

    GL HF

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

Discussions similaires

  1. quelques soucis avec word 2000
    Par ramchou dans le forum Word
    Réponses: 3
    Dernier message: 06/09/2004, 18h13
  2. SOucis avec une reequete imbriquee
    Par Ni4k dans le forum Langage SQL
    Réponses: 6
    Dernier message: 30/03/2004, 08h56
  3. souci avec un algorithme
    Par slider16 dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 22/03/2004, 17h17
  4. [DEBUTANT] petits soucis avec un prgm de chat
    Par LechucK dans le forum MFC
    Réponses: 8
    Dernier message: 19/01/2004, 16h52
  5. Réponses: 4
    Dernier message: 16/02/2003, 12h16

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