Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème concernant requêtes qui s'enchainent

Sujet résolu
    24 septembre 2021 à 15:42:06

    Bonjour,

    Je débute avec node js, mon problème est le suivant :

    J'aimerai récupérer des données d'une bdd, pour ça j'ai du imbriquer des requêtes dans une méthode.

    Ce que je comprends pas c'est que j'ai une erreur et j'ai l'impression que la deuxième requête ne fonctionne même pas.

    voici la méthode :

       static ListCommandes (idCompte,cb){
            connection.query('SELECT * FROM `commandes` WHERE idCompte = ?',[idCompte], (err, rows) => {
                if (err) throw err
                {
    
    
                    var commandes = [{
                        'numCommande' : [],
                        'nom' : [],
                        'prix': [],
                        'quantite': [],
                        'total': []
    
                    }]
    
    
                    for(var j = 0; j < rows.length; j++){
                        var arrIdProduits = rows[j].idProduits.split('_')
    
                        var arrPrix = rows[j].prix.split('_')
                        var arrQuantite = rows[j].prix.split('_')
                        for(var i = 0; i < arrIdProduits.length; i++){
    
                            console.log('produitID:'+parseInt(arrIdProduits[i]))
                           connection.query('SELECT * FROM `produits` WHERE idProd = ?', [parseInt(arrIdProduits[i])],(err, result) => {
                           if (err) throw err
                           {
    
                                console.log('ça ne passe pas ici ...')
                                commandes[j]['nom'][i] = result.libelle
                                commandes[j]['prix'][i] =  arrPrix[i]
                                commandes[j]['quantite'][i] = arrQuantite[i]
                           }
    
                        })
                        }
                        console.log('numcommande:')
                        console.log(commandes)
                        if(rows[j].numeroComm != 'undefined'){
                            commandes[j]['numCommande'][0] = rows[j].numeroComm
                            commandes[j]['total'][0] = rows[j].total
                        }
                    }
    
                    cb(commandes)
                }
            })
    
        }


    Merci d'avance pour votre aide.

    • Partager sur Facebook
    • Partager sur Twitter
      24 septembre 2021 à 16:09:30

      Oulà !

      Je suis vraiment pas une pointure en node, mais deux ou trois choses me semblent curieuses. Alors c'est peut-être juste que je connais pas ces syntaxes...

      Première chose, le mot-clé statique ne s'utilise-t-il pas uniquement au sein d'une classe?

      Deuxième chose, je ne comprend pas ta manière d'écrire la requête de façon dynamique ( mais encore une fois tu utilise peut-être un framework ou une tech que je ne connais pas ).
      Moi j'aurais tenté une concaténation toute simple, ex pour la ligne 2 :

      connection.query('SELECT * FROM `commandes` WHERE idCompte = ' + idCompte), ...)

      Bon, et du coup, si ta première requête provoque une erreur, la deuxième n'est pas exécutée.

      Vraiment navré de ne pouvoir t'aider vraiment, pour ma part j'utilise MongoDB, et je dois avouer que j'ai eu énormément de mal à intégrer les bases de la gestion de l'asynchrone ^^

      • Partager sur Facebook
      • Partager sur Twitter
        24 septembre 2021 à 16:15:52

        Merci pour ta réponse, j'ai effectivement oublié de préciser que c'est une méthode dans une class.

        La syntaxe est la bonne car je l'utilise partout.

        Je n'arrive juste pas à comprendre pourquoi ça ne fonctionne pas alors que j'ai déjà utilisé cette façon de faire ...

        Voici l'erreur :

        "TypeError: Cannot read property 'numCommande' of undefined"

        • Partager sur Facebook
        • Partager sur Twitter
          25 septembre 2021 à 8:17:45

          Je crois que ton code essaie de te dire qu'à la ligne 40, lorsque tu essaies de faire

          commandes[j]['numCommande']

          "commandes[j]" n'existe pas et que du coup, tu ne peux pas accéder à la propriété`numCommande` de quelque chose qui n'existe pas.

          Est ce que tu peux essayer de `console.log(commandes[j])` à peu près à ce niveau la ?

          ---

          Pour aller un peu plus loin dans le truc, j'ai l'impression que tu n'ajoutes jamais d'entrée dans ton tableau de commandes. Du coup, commandes[j], peu importe la valeur de j, n'existera jamais.

          -
          Edité par mfrachet 25 septembre 2021 à 8:22:57

          • Partager sur Facebook
          • Partager sur Twitter
            25 septembre 2021 à 22:43:41

            Bonjour,

            Tu viens de découvrir l'asynchrone. La ligne 45 est exécutée avant la ligne 26. Je ne sais pas quelle lib tu utilise, mais ce serais plus facile avec des promises. Avec des callbacks, il faut les transformer en promises. Je pense que tu vas avoir du mal à saisir ce concept (tu semble amateur de poo, en général c'est un concept qui passe mal si tu as de bonnes bases en poo), je n'ai malheureusement pas de bon tuto à te proposer. 

            https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise 

            Si tu donne le nom de ta lib, je pourrais t'aider un peu plus.

            • Partager sur Facebook
            • Partager sur Twitter
              28 septembre 2021 à 0:31:55

              Bonjour,

              Merci à tous pour vos réponses, effectivement je ne suis pas encore à l'aise avec l'asynchrone.

              Je suis en pleine auto formation :honte:

              J'ai donc pu avancer grace à tes conseils piero !

              J'ai une dernière question bête, là je ne vois pas comment l'asynchrone aurait un rapport :

              Dans le code qui suit je n'arrive pas à avoir après la deuxième requête la variable "j" à 0 et 1 alors qu'il n'y a pas de raison pour que ce soit évité...

                  static ListCommandes (idCompte,cb){
                      connection.query('SELECT * FROM `commandes` WHERE idCompte = ?',[idCompte], function(err, rows, fields) {
                          if (err) throw err
                          {
              
                              var commandes = [{
                                  'numCommande' : [null],
                                  'nom' : [null],
                                  'prix': [null],
                                  'quantite': [null],
                                  'total': [null]
              
                              }]
              
                              for(var j = 0; j < rows.length; j++){
              
                                  var arrIdProduits = rows[j].idProduits.split('_')
              
                                  var arrPrix = rows[j].prix.split('_')
                                  var arrQuantite = rows[j].quantites.split('_')
              
                                  commandes.push({
                                     'numCommande' : ['null'],
                                     'nom' : ['null'],
                                     'prix': ['null'],
                                     'quantite': ['null'],
                                     'total': ['null']
                                                })
              
                                  try{
                                      console.log('j avant requete:')
                                      for(var i = 0; i < arrIdProduits.length; i++){
              
                                         connection.query('SELECT * FROM `produits` WHERE idProd = ?', [arrIdProduits[i]],function(err, result, fields) {
              
              
                                         if (err) throw err
                                         {
                                          console.log('j:')
                                           console.log(j)
                                            console.log('produit:')
                                           console.log(result[0]['libelle'])
              
                                          commandes[j]['nom'][i] =  result[0]['libelle']
                                          commandes[j]['prix'][i]  =  arrPrix[i]
                                          commandes[j]['quantite'][i]  =  arrQuantite[i]
              
              
                                         }
                                      })
              
                                      }
                                     commandes[j]['numCommande'][0] = rows[j].numeroComm
                                     commandes[j]['total'][0] = rows[j].total
                                  } catch(ex){
                                      console.log("numCommande n'existe pas (erreur javascript : "+ex.toString()+")");
                                  }
              
                              }//fin for
              
                              setTimeout(() => {
                              console.log('commandes:')
                                  console.log(commandes)
                                  cb(commandes)
                                }, 1000);//
              
                          }
                      })
              
                  }

              Je ne comprends pas, pourtant on passe tout les produits voulu mais le "j" lui est toujours à 2...

              • Partager sur Facebook
              • Partager sur Twitter
                28 septembre 2021 à 6:54:42

                Je dis peut-être des bêtises, mais tu as bien j=0 ou 1 à la ligne 31, mais pas à la ligne 40 ?

                J'ai d'abord pensé au mot clé "let" au lieu de "var", mais à priori ce serait pas ça.

                Après, pour la portée des variables, il me semble que les arrow functions sont pratiques pour ça. Enfin moi du coup je les met dans toutes mes callbacks, justement parce que j'ai déjà eu ce genre de problème.
                Donc à la ligne 34, tu peux essayer ça.

                Dernier point, et ce n'est pas pour faire la leçon, mais j'ai eu aussi des problèmes très étranges, dont l'origine est parfois difficile à pister, à cause des point-virgules oubliés à la fin d'une instruction. Bon, je dis ça mais la syntaxe ayant beaucoup changé entre le moment où j'ai appris et pratiqué la javascript ( il y a bien 10 ans ) et aujourd'hui...

                Après, tu peux quand même essayer, ligne 31 :

                console.log('j avant requete : ' + j);

                et lignes 39 à 42 :

                console.log('j : ' + j);
                console.log('produit:');
                console.log(result[0]['libelle']);




                -
                Edité par LucasWerquin 28 septembre 2021 à 6:56:19

                • Partager sur Facebook
                • Partager sur Twitter
                  28 septembre 2021 à 12:08:39

                  setTimeout(() => {
                    console.log('commandes:')
                    console.log(commandes)
                    cb(commandes)
                  }, 1000);//

                  C'est horrible. Utilise des promises, c'est fait pour ça. Rien ne te garantis que pour j = 0 tu as ton résultat avant 1s.

                  Il faut plutôt faire qqch comme ça :

                  static ListCommandes (idCompte,cb){
                      function query(queryString, params) {
                          //tu peux mettre cette fonction n'importe où à partir du moment où tu as connexion
                          //si ça se trouve, c'est inutile de faire ça si la lib que tu utilise peut faire des promises
                  
                          return new Promise((resolve, reject) => {
                              connexion.query(queryString, params, (err, res, fields) => {
                                  if (err) reject(err);//on ne throw pas dans une promise, on reject
                                  resolve(res);
                              })
                          })
                      }
                  
                      //pas besoin d'initialiser vive le js
                      //on vas faire une hashtable d'abord, pour éviter de faire plein de boucles
                      const commandes = {};
                      console.log('début');
                      query('SELECT * FROM `commandes` WHERE idCompte = ?',[idCompte]);
                  
                          .then(rows => {
                              console.log('then 1');
                              const promises = [];
                  
                              for(const row of rows) {
                                  const arrIdProduits = row.idProduits.split('_');
                                  const arrPrix = row.prix.split('_');
                                  const arrQuantite = row.quantites.split('_');
                  
                                  //pas besoin de mettre de '', ce sont des string
                                  commandes[row.numeroComm] = {
                                      numCommande: [row.numeroComm],
                                      nom: ['null'],
                                      prix: arrPrix,
                                      quantite: arrQuantite,
                                      total: [row.total]
                                  }
                  
                                  for(const id of arrIdProduits) {
                                      promises.push(query('SELECT * FROM `produits` WHERE idProd = ?', [id]));
                                  }
                              }
                  
                              console.log('commandes : ', commandes);
                              
                              //ça permet d'attendre d'avoir tous les résultats que ça prenne 0.1s ou 10 min
                              //c'est quand même mieux qu'un timeout 
                              return Promise.all(promises);
                          })
                  
                          .then(rows => {
                              console.log('then 2');
                              //ici tu as tous tes résultats
                              console.log('rows : ', rows);
                              
                              for(const row of rows) {
                                  //il faut trouver un moyen de récup numCommande dans row
                                  const numCommande = row.idProd;
                                  
                                  //c'est pour ça la hashtable, ça évite de faire une autre boucle ici
                                  //pas besoin de test si commandes[numCommande] existe, vu qu'on catch après ça ne vas pas tout casser
                                  commandes[numCommande].nom = [row.libelle];
                              }
                              
                              
                              cb(
                                  Object.values(commandes)//on transforme la hashtable en tableau
                              );
                          })
                  
                          .catch(err => {//ça permet de catch si il y a une erreur dans query ou que la promise reject
                              console.log(`erreur js : ${err}`);
                          })
                      
                          .finally(() => {
                              //si tu veux faire quelque chose à la fin, que ça catch ou que tout se passe bien
                              console.log('fin');
                          })
                      
                      console.log('fin du code');
                      setTimeout(() => {console.log('1s après fin du code')}, 1000);
                  }

                  Je sais pas si tu connais les fonction fléchées, donc petit ajout :

                  () => {...}
                  //pour le moment, on vas dire que c'est pareil que
                  function() {...}

                  En js, les ";" en fin de ligne ne sont pas obligatoire. Tu peux les oublier sans problème. C'est toujours mieux si il y en a, mais ce n'est qu'une question de style.

                  Au passage, je crois que tu as moyen de faire une seule requête SQL, avec une jointure, mais je ne suis pas à l'aise sur ce point.


                  -
                  Edité par piero5673 28 septembre 2021 à 12:16:03

                  • Partager sur Facebook
                  • Partager sur Twitter
                    30 septembre 2021 à 23:12:03

                    Merci beaucoup pour ton aide piero,

                    Mon code fonctionne et je peux enfin continuer le développement du site !

                    Bonne soirée à tous :)

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Problème concernant requêtes qui s'enchainent

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    • Editeur
                    • Markdown