2016-10-13 3 views
3

Ich habe zwei Abfragen.
Die erste,node.js mysql Abfrage in einer for-Schleife

SELECT auctions.name, wowitemdata.itemName, auctions.itemId, 
auctions.buyout, auctions.quantity 
FROM auctions 
INNER JOIN wowitemdata ON auctions.itemId = wowitemdata.itemID; 

gibt Daten wie folgt aus:

{ 
name: 'somename', 
itemName: 'someitemname', 
itemId: '0000', 
buyout: '0001', 
quantity: '5', 
} 

Die zweite Abfrage verwendet Daten aus dem # 1 die count() von Artikel billiger als itemId zu bekommen. Die Antwort soll zu # 1 als neues Element -> 'Unterschnitt' hinzugefügt werden.

Meine Funktion:

function checkUndercut(data, length){ 
    var Select = 'SELECT COUNT(auctions.itemId) AS cnt '; 
    var From = 'From `auctions` '; 
    var Where = 'WHERE auctions.itemId LIKE ? AND buyout < ?'; 
    var sql = Select + From + Where; 
    for(i = 0, len = length; i < len; i++){ 
     var inserts = [data[i]['itemId'], data[i]['buyout']]; 
     var ssql = mysql.format(sql, inserts); 
     data[i]['undercut'] = i; 
     connection.query(ssql, function(err, rows, fields){ 
      if(!err){ 
       console.log("check Undercut: " + rows[0].cnt); 
       data[i]['undercut'] = rows[0].cnt; 
      } else { 
       console.log("Error while performing Query"); 
      }; 
     }); 
    }; 
} 

Durch die asynchrone Art der Abfrage ich nicht die for-Schleife i var die Daten anhängen können.
Wie komme ich dazu?

Edit: Mein neues Problem:
Als ich nach einem Namen (searchobj) zu suchen, die zurückgegebenen Daten einen Schritt zurück.
Angenommen, ich suche nach "Tim", nichts wird angezeigt.
Angenommen, ich suche als nächstes nach "Finn", meine Daten zu "Tim" werden angezeigt.

Ich vermute, das liegt an der Art, wie ich Daten aus meiner checkUndercut-Funktion bekommen habe.
Ich habe einen neuen Top-Level-var, appdata und nach @simple_programmers Vorschlag mit Ich habe meinen neuen Code wie folgt:

function(err){ 
     if(err){ 
      //handle the error if the query throws an error 
     }else{ 
      appdata = data; 
      console.log(appdata); 
      //whatever you wanna do after all the iterations are done 
     } 
    }); 

Die console.log sendet die richtigen Informationen aus, so mein Problem mit der Funktion get liegt das Senden die Antwort vorzeitig.

Meine get-Funktion:

app.get('/test',function(req, res) { 
    console.log("app.get "+searchobj); 
    var sqlSELECT = 'SELECT auctions.name, wowitemdata.itemName, auctions.itemId, auctions.buyout, auctions.quantity '; 
    var sqlFROM = 'FROM `auctions` '; 
    var sqlINNER ='INNER JOIN `wowitemdata` ON auctions.itemId = wowitemdata.itemID '; 
    var sqlWHERE = 'WHERE auctions.name LIKE ?'; 
    var sql = sqlSELECT + sqlFROM + sqlINNER + sqlWHERE; 
    var inserts = [searchobj]; 
    var sql = mysql.format(sql, inserts); 
    //console.log("Query: "+sql); 
    connection.query(sql, function(err, rows, fields) { 
     if (!err){ 
     var rowLen = rows.length; 
     checkUndercut(rows, rowLen); 
     console.log(appdata); 
     res.send(appdata); 
       } else { 
    console.log('Error while performing Query.'); 
    }; 

    }); 
}); 

Meine Fragen:

1 Was ist der richtige Weg, um Daten aus einer Asynchron-Funktion zum Senden?

2 Gibt es einen Weg, wie ich meine app.get oder res.send warten kann, bis meine Daten abgerufen werden, bevor sie gesendet werden?

Edit 2: Ich kann es funktionieren, indem Sie den gesamten Code in meine app.get(), aber es muss eine elegantere und einfacher zu lesende Lösung sein?

+0

Was ist Ihre erste Abfrage? Ich frage, weil es * enorm * vorzuziehen ist, sie zusammen in eine gespeicherte Prozedur zusammenzufassen, beitreten/subselect, als viele Daten in der Datenbank zu haben (es kann fast sicher die Daten für Sie sammeln). – msanford

+0

Die erste Abfrage lautet wie folgt: 'SELECT auctions.name, wowitemdata.itemName, auctions.itemId, auctions.buyout, auctions.quantity FROM 'auctions' INNER JOIN' wowitemdata' ON auctions.itemId = wowitemdata.itemID' Edit: Damn Formatierung – user45706

Antwort

4

Der beste Weg, dies meiner Meinung nach zu tun ist, ein Knotenmodul async genannt zu verwenden, um Dinge parallel laufen zu lassen und einen Rückruf, wenn alles fertig ist.

Es gibt eine Vielzahl von Methoden in async Modul für diese Art von Situationen definiert und die, die ich empfehlen würde, ist forEachOf.

Da Ihre data Parameter ein Array ist, es etwas geht -

function checkUndercut(data, length){ 
    var Select = 'SELECT COUNT(auctions.itemId) AS cnt '; 
    var From = 'From `auctions` '; 
    var Where = 'WHERE auctions.itemId LIKE ? AND buyout < ?'; 
    var sql = Select + From + Where; 
    async.forEachOf(data, function (dataElement, i, inner_callback){ 
     var inserts = [dataElement['itemId'], dataElement['buyout']]; 
     var ssql = mysql.format(sql, inserts); 
     dataElement['undercut'] = i; 
     connection.query(ssql, function(err, rows, fields){ 
      if(!err){ 
       console.log("check Undercut: " + rows[0].cnt); 
       dataElement['undercut'] = rows[0].cnt; 
       inner_callback(null); 
      } else { 
       console.log("Error while performing Query"); 
       inner_callback(err); 
      }; 
     }); 
    }, function(err){ 
     if(err){ 
      //handle the error if the query throws an error 
     }else{ 
      //whatever you wanna do after all the iterations are done 
     } 
    }); 
} 

Also, was ist im Grunde tut, ist, es über die data Array-Schleifen und führt die Abfrage für jedes Element des Arrays. Sobald die Abfrage ausgeführt ist, gibt sie einen Aufruf an die Callback-Methode, die für diese Iteration lokal ist. Sobald alle Iterationen durchgeführt sind (d. H. Der letzte lokale Rückruf wird aufgerufen), ruft er den letzten Rückruf auf, in dem Sie tun können, was Sie später tun möchten, wenn alle Ihre Abfragen ausgeführt sind.

Mehr über forEachOf hier - https://caolan.github.io/async/docs.html#eachOf

Async Modul - https://caolan.github.io/async/

+0

Ich bin sehr neu in der Magie, die Async ist, also bitte bitte mit mir. Ich habe Probleme, meine app.get-Funktion zu bekommen, um Daten in der richtigen Reihenfolge zu senden, mit der (wahrscheinlich Umweg) Art, die ich "repariert" habe, sind meine Suchen einen Schritt zurück. Angenommen, ich suche nach "Tim", nichts wird angezeigt. Angenommen, ich suche als nächstes nach "Finn", meine Daten zu "Tim" werden angezeigt. Ich bearbeite meinen ursprünglichen Beitrag, um diese neuen Fragen zu reflektieren. – user45706

0

Wenn Sie nur besorgt sind über die Festlegung der i, um den Wert bei einem bestimmten Index zu erhalten, verwenden Sie einfach array.forEach.

data.forEach(function(datum, i){ 
    var inserts = [datum['itemId'], datum['buyout']]; 
    var ssql = mysql.format(sql, inserts); 
    datum['undercut'] = i; 
    connection.query(ssql, function(err, rows, fields){ 
    ... 
    datum['undercut'] = rows[0].cnt; 
    ... 
    }); 
    ... 
}); 
Verwandte Themen