hernry: node mysql2.query await

Hallo,

um mein "Programm" zu initialisieren muss ich aus einer mysql Datenbank diverse Tabellen lesen. Dies muss ich nacheinander machen, da Werte aus der ersten Tabelle zum suchen für die zweite Tabelle nötig sind.

Wenn ich jetzt den query Aufruf mit callback mache, läuft das Programm weiter ohne das die ersten Daten schon tatsächlich aus der Datenbank gelesen zu wurden.

Ich möchte aber auch nicht alle query-Aufrufe mittels callback verschachteln.

Da es nur zum initialisieren des Hauptprogramms einmalig nötig ist, möchte ich den query-Aufruf so gestalten, das das Programm erst weiter läuft, wenn ich die Daten aus der Datenbank gelesen habe.

aktuell habe ich Aufruf der query-Funktion mittels callback so gelöst.

function read_spsliste(spsname){
    var sql = 'SELECT * FROM spsliste WHERE spsname = ?';

        conn.query(sql, spsname,
            function (err, results, fields) {
            if (err) throw err;
            else 
                console.log(results[0].spsname + ' # ' + results[0].ip + ' # ' + results[0].mpi + ' # ' + results[0].zyclus);
                sps_name =results[0].spsname;
                sps_ip =results[0].ip;
        })
};
Quelltext hier

Gibt es hier andere "query-Aufrufe" die "warten" bis alle Daten aus der Datenbank gelesen wurden, oder kann ich dies "manipulieren" das eine "Wartezeit" abläuft ... ???

Bin node "Greenhorn" ;-)

Danke
 henry
  1. Tach!

    Dies muss ich nacheinander machen, da Werte aus der ersten Tabelle zum suchen für die zweite Tabelle nötig sind.

    Joins oder Corellated Subquerys sind keine Option?

    Wenn ich jetzt den query Aufruf mit callback mache, läuft das Programm weiter ohne das die ersten Daten schon tatsächlich aus der Datenbank gelesen zu wurden.

    Wenn nur Callbacks zur Verfügung stehen, kommst du um das Schachteln nicht herum. Wenn das System zusätzlich bietet, statt Callbacks ein Promise zu liefern, kannst du das nehmen. Damit kommt man schon einen Schritt aus der Verschachtlungsebene heraus. Ob das zur Verfügung steht, sagt dir die Dokumentation der von dir verwendeten Datenbank-Library. Und wenn du das hast, kannst du auch auf async await umsteigen, was letztlich nur Syntactic Sugar für das Promise-Handling ist. Damit fühlt es sich synchron an.

    Ich möchte aber auch nicht alle query-Aufrufe mittels callback verschachteln.

    Wenn keine Promises angeboten werden, kannst du immer noch selbst ein Promise drumherumbauen, und das dann "async-awaiten".

    dedlfix.

  2. Hallo henry,

    welchen Mysql-Treiber verwendest Du? mysql von Doug Wilson oder mysql2 von Andrey Sidorov (sidorares)?

    mysql2 bietet Promises an und scheint auch noch eher in Pflege zu sein. Doug Wilson hat seit 2 Jahren nichts mehr geändert.

    Das habe ich jetzt nur durch eine schnelle NPM Suche ermittelt, ich kann Dir nicht sagen, ob mysql2 soviel taugt wie Andrey vorschwärmt.

    Mit einer fertigen, promisegestützten Version kannst Du await verwenden und musst nicht selbst eine Promisehülle bauen. KANN man natürlich auch selbst tun

    function queryAsync(conn, sql, args) {
       return new Promise( (resolve, reject) => {
          conn.query(sql, args, (err, results, fields) => {
             if (err) 
                reject(err);
             else
                resolve { results, fields };
          });
       });
    }
    
    // der folgende Code muss in einer async-Funktion stehen!
    
    async function read_spsliste(spsname) {
      let ergebnis1 = await.queryAsync(conn, "...", [ ... ]);
      // use ergebnis1.results and ergebnis1.fields
    
      let ergebnis2 = await.queryAsync(conn, "...", [ ... ]);
      // use ergebnis2.results and ergebnis2.fields
    
      let ergebnis3 = await.queryAsync(conn, "...", [ ... ]);
      // use ergebnis3.results and ergebnis3.fields
    }
    

    Wenn Du read_spsliste aufrufst, bekommst Du ein Promise zurück, und zwar sofort, ohne Wartezeit. Das musst Du wieder mit await erwarten - was voraussetzt, dass der Aufrufer selbst eine async-Funktion ist. Fehler bekommst Du als Exception.

    Oder Du verwendest das Promise ungezuckert, also so:

    read_spsliste(conn, spsname)
    .then(liste => // verarbeite liste)
    .catch(error => // verarbeite fehler);
    

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo,

      vielen Dank für eure Tips. Ich benutze mysql2 von Andrey Sidorov, da ich mit mysql Probleme bei der Authorisierung der Datenbank hatte.

      Ich werde es probieren und geben Rückmeldung.

      Vielen Dank 
      
         henry
      
      1. Hallo,

        ich habe es nun umzusetzen versucht. Anbei mein Code:

                       rows = read_spsliste(conn, 'T1');
                       sps_name =rows[0].spsname;
        
        /*##########################################################################################*/
        async function read_spsliste(conn, spsname) {
            let sql = 'SELECT * FROM spsliste WHERE spsname = ?';
            let ergebnis = await queryAsync(conn, sql, spsname);
        
            return ergebnis.results;
        }
        /*******************************************************************************************/
        function queryAsync(conn, sql, args) {
           return new Promise( (resolve, reject) => {
              conn.query(sql, args, (err, results, fields) => {
                 if (err) 
                    reject(err);
                 else
                    resolve ( results, fields );
              });
           });
        }
        
        /*############################################################################################
        

        Es kommt kein Rückgabewert über "rows" zurück. Ich, kann mir das nicht erklären ... oder sitze auf der Leitung ;-)

        Danke

        1. Tach!

          Es kommt kein Rückgabewert über "rows" zurück. Ich, kann mir das nicht erklären ... oder sitze auf der Leitung ;-)

          Das ist Grundlagenwissen zu async-await. Wenn eine Funktion async ist, gibt sie ein Promise zurück. Das eigentliche Ergebnis bekommst du, wenn du abwartest, bis das Promise erfüllt ist, also musst du ein await verwenden.

          Und dass es keinen Rückgabewert gäbe, halte ich für ein Gerücht. Ein concole.log() wäre nützlich gewesen, um den Rückgabewert zu analysieren.

          dedlfix.

          1. Hallo dedlfix,

            wie schon im 1. Thread geschrieben, bin ich Node-Greenhorn. Mit der Umsetzung habe ich noch meine Schwierigkeiten und das ist untertrieben ;-)

            Bitte kurz ein Beispiel anhand meines Codes. Ich will keinen fertigen Code, aber ich möchte es verstehen können.

            Danke

            1. Tach!

              wie schon im 1. Thread geschrieben, bin ich Node-Greenhorn. Mit der Umsetzung habe ich noch meine Schwierigkeiten und das ist untertrieben ;-)

              Deswegen erwähnte ich, dass das Grundlagenwissen ist, und in jedem Tutorial zu async-await erklärt werden muss.

              Bitte kurz ein Beispiel anhand meines Codes.

              Du hast bereits ein await in deinem Code stehen. Es wird immer auf dieselbe Weise verwendet. Ohne ein vorangestelltes await gibt die Funktion ein Promise zurück, mit await den Wert nach seiner Erfüllung.

              Zu beachten ist auch, dass await im Top Level nur unter bestimmten Bedingungen verwendet werden kann.

              dedlfix.

            2. Hallo Henry,

              Eine async-Funktion kehrt sofort zurück, ja, isso, works as designed.

              Deswegen liefert sie ein Promise, auf das Du warten musst. Mit await oder mit .then(). Beispiele findest Du in meinem Posting von gestern.

              async und await sind wie Corona. Wenn sie erstmal an einer Ecke Fuß (oder Lunge) gefasst haben, breiten sie sich überall hin aus. Es sei denn, du setzt Dich mit .then()/.catch() zur Wehr...

              Das ist aber nicht Node-spezifisch, sondern ein generelles Thema für neueres JavaScript.

              Rolf

              --
              sumpsi - posui - obstruxi