Uri: Auf mysql Result in node.js zugreifen.

Hallo,

ich habe mit node.js angefangen und weiß nicht wie ich serverseitig zugreife. Ich möchte für auf mein json Objekt zugreifen, um diesen im lupus einzusetzen, aber ich bekomme die Fehlermeldung

TypeError: Cannot read property 'buildingsCounter' of undefined

Hier ist der Code


function getBuildingInformationForEach(){
  var counter;
app.get('/count_buildings', function(req, res) {                                                    
    var connection = mysql.createConnection({
      host     : 'localhost',
      user     : 'root',
      password : ''
    });
    connection.connect();
    connection.query('sqlQuery', function(err, results) {
        if (err) throw err;
        counter ={buildingsCounter:results};
        console.log("Hallo: "+counter[0].buildingsCounter[0].count);
        res.json(counter);
      });
    connection.end();
});
  
lupus(0, counter.buildingsCounter[0].count, function(n) {
  
  app.get('/Buildings_Details-'+n, function(req, res) {                                                    
    var connection = mysql.createConnection({
      host     : 'localhost',
      user     : 'root',
      password : ''
      
    });
    connection.connect();
    connection.query('sqlQuery', function(err, rows, fields) {
      if (err) throw err;
     
      res.json({Wohnungen:rows});
    });
    connection.end();
});
  
}, 
function() {
  console.log('All done!');
}); 
 
};

Woran liegt das?

Gruß Uri

  1. Hallo Uri,

    Computer tun immer, was man ihnen sagt. Das ist nicht unbedingt das, was man will…

    counter ={buildingsCounter:results};
    

    Dieser Befehl erzeugt ein Objekt mit einem Property 'buildingsCounter', das den Wert der Variablen results hat.

    console.log("Hallo: "+counter[0].buildingsCounter[0].count);
    

    Aber das greift auf das Property '0' dieses Objekts zu und erwartet dahinter ein Objekt, das eine Eigenschaft buildingsCounter hat. Da Du das Property '0' nicht gesetzt hast, ist das undefined.

    Rolf

    --
    Dosen sind silbern
    1. Hallo Rolf,

      Zuerst habe ich

      counter.buildingsCounter[0].count
      

      und bekam die Fehlermeldung

      TypeError: Cannot read property 'buildingsCounter' of undefined

      wie mach ich das richtig?

      Danke und Gruß

      Amit

      1. Tach!

        Zuerst habe ich

        counter.buildingsCounter[0].count
        

        und bekam die Fehlermeldung

        TypeError: Cannot read property 'buildingsCounter' of undefined

        wie mach ich das richtig?

        Am besten beachtest du den Geltungsbereich von Variablen. counter existiert nur in der Funktion getBuildingInformationForEach, die außerdem nicht mal aufgerufen wird. Innerhalb einer Funktion etwas erzeugen, das global sein soll, ist keine gute Herangehensweise. Gib das lieber als Funktionsergebnis zurück.

        dedlfix.

        1. Jetzt bin ich verwirrt. counter ist definiert in getBuildingInformationForEach(), müsste also in app.get('/count_buildings', ...); doch existieren? Die Console.log() innerhalb app.get('/count_buildings', ...); werden aus irgendeinem Grund nicht ausgeführt.

          function getBuildingInformationForEach(){
            
            
            var counter;
            console.log("1. type: " + typeof(counter));
          
          app.get('/count_buildings', function(req, res) { 
            console.log("type: " + typeof(counter));
              var connection = mysql.createConnection({
                host     : 'localhost',
                user     : 'root',
                password : ''
              });
              connection.connect();
              connection.query('sqlQuery', function(err, results) {
                  if (err) throw err;
                  counter ={buildingsCounter:results};
                  console.log("2. type: " + typeof(counter));
                  res.json(counter);
                    
          
                });
              connection.end();
          });
            
          lupus(0, 1, function(n) {
            console.log("3. type: " + typeof(counter));
            app.get('/Buildings_Details-'+n, function(req, res) {                                                    
              var connection = mysql.createConnection({
                host     : 'localhost',
                user     : 'root',
                password : ''
                
              });
              connection.connect();
              connection.query('sqlQuery', function(err, rows, fields) {
                if (err) throw err;
               
                res.json({Wohnungen:rows});
              });
              connection.end();
          });
            
          }, 
          function() {
            console.log('All done!');
          }); 
           
          };
          
          getBuildingInformationForEach();
          
          

          Das sagt die Konsole, wenn ich den Server starte.

          1. type: undefined

          Example app listening on port 8080!

          1. type: undefined

          All done

          Gruß Uri

          1. Tach!

            Jetzt bin ich verwirrt.

            Ja, und du hast mich auch irregeführt, weil du deinen Code nicht ordentlich eingerückt hast. So hab ich angenommen, dass getBuildingInformationForEach vor dem lupus-Aufruf zu Ende ist.

            counter ist definiert in getBuildingInformationForEach(), müsste also in app.get('/count_buildings', ...); doch existieren?

            Ja. Es ist nun nicht der Geltungsbereich, sondern die zeitliche Reihenfolge der asynchronen Ausführung, die du berücksichtigen musst. Wenn irgendetwas einen Callback aufruft, nachdem es seine Arbeit erledigt hat, dann kannst du sämtlichen Code, der auf das Ergebnis angewiesen ist, nur in diesen Callback-Aufruf schreiben, oder in Code, der davon aus aufgerufen wird. Fortgeschrittene nehmen Promises, um damit die Verschachtlungstiefe zu verringern und den Code besser trennen zu können.

            Die Console.log() innerhalb app.get('/count_buildings', ...); werden aus irgendeinem Grund nicht ausgeführt.

            Die Funktion lupus() hat sich entschieden, die anonyme Funktion mit dem 'All done' drin, die du als vierten Parameter übergeben hast, aufzurufen. Warum auch immer.

            Die Callbacks in den app.get()-Aufrufen werden auch aus irgendeinem Grund nicht mehr angesprochen. Ich nehme an, ihr Aufruf kommt einfach zu spät und der Router ist bereits fertig mit Routen, so dass deren Routen nicht mehr berücksichtigt werden können, weswegen dann auch nicht mehr ihre Callbacks aufgerufen werden können.

            dedlfix.

          2. Hallo Uri,

            ich bin kein node Experte, aber schnelles googeln führt mich bezüglich app.get zu Express.js und dass man hier Routen definiert, die dann von node behandelt werden.

            Allerdings verstehe ich deine Vorgehensweise nicht wirklich und möglicherweise rühren deine Probleme daher, dass Du das auch nicht tust 😉

            /count_buildings - ermittelt eine Anzahl von Gebäuden und liefert die Anzahl als JSON an den Aufrufer zurück.

            Wichtig zu verstehen ist, dass die hier hinterlegte Callback-Funktion, d.h. die SQL Query, erst stattfindet, wenn der Client die /count_buildings URL abruft. Nicht vorher.

            Als zweites möchtest Du für jedes gefundene Gebäude eine eigene Route definieren: /Buildings_Details-n, mit n=0,1,2,... und du verwendest lupus, um die Definitionsschleife asynchron zu kapseln.

            Dieser Ansatz hat eine MENGE Probleme.

            1. Findet die Routendefinition für die Details zu einem Zeitpunkt statt, wo der der Client die Gebäudeanzahl noch gar nicht abgerufen hat.
            2. Ist es eigentlich nicht sinnvoll, diese Anzahlabfrage und die Routendefinition für die Details zu koppeln. Was passiert, wenn jemand /count_buildings mehrfach aufruft und dein Code das täte, was du willst? Du würdest alle Routen mehrfach definieren.
            3. Ist lupus, wenn ich die Doku richtig lese, dann interessant, wenn Du VIELE Schleifendurchläufe hast und eine for() Schleife einfach ein Ressourcenschwein wäre. Das hast Du hier aber nicht. Oder wenn doch, beginnen die Probleme erst richtig.
            4. Ist eine eigene Route für jedes Gebäude sicherlich nicht die richtige Idee. Wenn lupus hier tatsächlich sinnvoll wäre, dann würdest Du damit tausende von Routen definieren, und dann hättest Du express.js wahrscheinlich zu bimmelbahn.bas degradiert. Besser wäre, wenn der Client die Gebäudenummer als Parameter übergibt, also /Buildings_Details/n statt /Building_Details-n. Wie man das genau mit express.js macht, weißt Du vermutlich besser als ich.
            5. Ist die Identifikation eines Gebäudes per laufender Nummer vermutlich auch nicht sinnvoll.

            Meine Vorstellung einer sinnvollen Lösung wäre eigentlich diese:

            • Zwei Routen definieren: /buildings_index und /buildings_details/id
            • /buildings_index liefert dem Client eine Liste aller Gebäude, mit ID und Name oder so, woraus der Client eine Übersicht mit Detail-Links aufbereiten kann.
            • /buildings_details/id wäre dann bookmarkable und kann die Details zu einem bestimmten Gebäude ermitteln.

            Rolf

            --
            Dosen sind silbern
  2. direkt in meiner server.js steht das hier

    app.get('/getSkillData', function (req, res) {
        if(req.session.email) {
            var sqlite3 = require('sqlite3').verbose();
            var db = new sqlite3.Database('skills.db');
    
            var data = db.all("SELECT skill as skill,subskill as subskill, name as name, nivau as nivau FROM skill_data where email='" 
                + req.session.email + "' order by name, skill, subskill", function(err, rows) {
                res.type('json');
                res.send(rows);
            });
            db.close();
        }
    });
    

    clientseitig rufe ich das dann so auf:

     $.ajax({
                url : "/getSkillData",
                dataType: "JSON",
                type: "GET",
                success: function (data) {
                
                for(var i = 0; i < data.length; i++) {
                    addTableRowParam(data[i].name, data[i].skill, data[i].nivau);
                }
                addTableRowParam("", "", "");
                }
            });
    
    1. mein app.get('/getSkillData', function (req, res) { steht übrigens direkt in meiner server.js ohne dass da noch eine funktion drüberhängt