2017-08-25 4 views
0

Ich versuche, eine Datenbank abzufragen, dann ein Array von Objekten aus den Ergebnissen zu machen, um sie in ein JSON-Objekt umzuwandeln.Zurückgeben von Ergebnissen mit Rückrufen

Ich bin nicht an asynchrone Art von Javascript gewöhnt und ich bin wirklich verwirrt darüber, wie man etwas implementiert, das synchron arbeiten muss. Ich weiß, dass ich wahrscheinlich Callbacks verwenden muss, aber nachdem ich mir viele Tutorials angeschaut habe, bin ich nur noch verwirrter.

Dies ist der Code ohne Rückrufe:

var foreignTable = (tablename,idArr)=>{ 
 
\t var dataArray = []; 
 
\t //call a query for each of the ids 
 
\t var objectToAdd; 
 
\t for(var id of idArr){ 
 
\t \t objectToAdd = queryForeignTable(tablename,id); 
 
\t \t dataArray.push(objectToAdd); 
 
\t } 
 
\t return dataArray; 
 
\t 
 
connection.end(); 
 
}; 
 

 
var queryForeignTable = (tablename,id)=>{ 
 
\t connection.query("SELECT * FROM "+tablename+" WHERE id="+id, function (error, results, fields) { 
 
\t if(error)throw error; 
 
\t var objectToAddToArray={}; 
 
\t //Go through each field in a result and make the object 
 
\t for(packet of fields){ 
 
\t \t var label = packet.name; 
 
\t \t objectToAddToArray[label] = results[0][label]; 
 
\t } 
 
\t 
 
\t return objectToAddToArray; 
 

 
}); 
 
}; 
 

 
var arrayOfDrivers = foreignTable("driver",[1,2]); 
 
    
 
outputJson["drive"]=arrayOfDrivers; 
 

 
console.log(outputJson); // { drive: [ undefined, undefined ] }

ich foreignTable(tablename, idArr, callback) mit dem Rückruf versucht Aufruf queryForeignTable ohne Glück.

Kann jemand erklären, wie ich diesen Code mit Callbacks arbeiten kann?

+1

Wahrscheinlich möchten Sie * ES7 Async-Funktionen (async/erwarten) * überprüfen. Z.B. dies [Präsentation] (http://rossboucher.com/await/) – oneturkmen

+0

learnyounode ist ein großes Tutorial, wenn Sie es nicht schon versucht haben https://github.com/workshopper/learnyounode –

Antwort

0

Eine Callback-Funktion ist eine Funktion, die in eine andere Funktion als Argument übergeben wird, die dann innerhalb der äußeren Funktion aufgerufen wird, um eine Art von Routine oder Aktion auszuführen.

von MDN: Callback function

Rückrufe sind ein Weg, um eine Funktion zu sagen, was als nächstes zu tun, wie in „nachdem Sie fertig sind, diese Funktion starten“.

Zum Beispiel:

first = function (callback) { 
    console.log("First!"); 
    callback(); 
} 

second = function() { 
    console.log("Second!"); 
} 

first(second); 

produzieren:

First! 
Second! 

Sie auch anonyme Funktion Produkt das gleiche Ergebnis verwenden können:

first(function() { 
    console.log("Second!") 
}); 

In Bezug auf das spezifische Beispiel aus Ihrer Frage , Sie sind richtig, dass Sie Callbacks ein bisschen anders verwenden müssen. Anstatt eine return Anweisung in jeder Ihrer beiden Funktionen zu verwenden, müssen Sie einen Rückruf verwenden. connection.query kommt asynchron mit Ihren Ergebnissen als results zurück, aber Sie können nicht return sie zu Ihrer queryForeignTable Funktion. Stattdessen geben Sie queryForeignTable eine Callback-Funktion zum Ausführen. Die gleiche Idee gilt für Ihre foreignTable Funktion.

Ich bin nicht zu Ihrer Datenbank verbunden ist, offensichtlich, so drückte ich eine DB-Verbindung und vereinfacht, was Sie zu tun versuchen, aber es sollte in etwa so aussehen:

// Stubbed DB connection 
var connection = {}; 
connection.query = (id, cb) => { 
    var results = [ 
    { 
     id: id, 
     name: 'Name of ' + id, 
    }, 
    ]; 
    cb(null, results); 
}; 

var foreignTable = (ids, cb) => { 
    var data = []; 
    for (var i = 0; i < ids.length; i++) { 
    queryForeignTable(ids[i], (error, obj) => { 
     data.push(obj); 
     if (i == ids.length - 1) { 
     cb(null, data); 
     } 
    }); 
    } 
}; 

var queryForeignTable = (id, cb) => { 
    connection.query(id, (error, results) => { 
    if (error) { 
     cb(error, null); 
    } 
    cb(null, results[0]); 
    }); 
}; 

foreignTable([1, 2], (error, data) => { 
    if (error) { 
    console.error(error); 
    } 
    console.log(data); 
}); 

Das erzeugt:

[ { id: 1, name: 'Name of 1' }, { id: 2, name: 'Name of 2' } ] 

im Wesentlichen, wenn Sie den Drang zu return einen gewissen Wert (e) aus einer Funktion in einer asynchronen Art und Weise, geben Sie der Funktion einen Rückruf Parameter, dann diesen Rückruf mit Ihrer Rückkehr Werte aufrufen.

Sie können den Code hier laufen: https://repl.it/K0YI/3

0

Wenn Sie einen asynchronen Aufruf haben, wie connection.query(statement, callback), dann, was Sie mit den Ergebnissen dieses Anrufs tun wollen muss innerhalb der Callback durchgeführt werden.

Bedenken Sie, dass Async-Funktionen nicht den endgültigen Wert zurückgeben, den Sie normalerweise möchten (normalerweise geben sie zurück). Anstatt einen Rückgabewert zu verwenden, übergeben Sie einen Rückruf, um zu sagen: "Wenn Sie fertig sind, machen Sie weiter und machen Sie dies mit den Ergebnissen", aka. Fortsetzungsstil.

Eine der Herausforderungen in Ihrem Code besteht darin, dass Sie separate Abfragen für jede ID ausgeben und anschließend die Ergebnisse in einer Reihe von Antworten aggregieren. Das bedeutet, dass Sie prüfen müssen, wann alle Abfragen abgeschlossen wurden, und erst dann die endgültigen Ergebnisse anzeigen.

Hier ist Ihr Beispiel, neu geschrieben, kommentiert und vereinfacht. Hoffentlich hilft dies zu erklären, wie der Kontrollfluss funktioniert.

// Read row IDs 1 and 2 from the "driver" table. 
readTable("driver", [1, 2], displayData); 

// Print the results. 
function displayData (arrayOfDrivers) { 
    console.log(arrayOfDrivers); 
} 

// Read all rows matching IDs in `idArray` from `tableName`, 
// put results into an array, and finally invoke `callback`. 
function readTable (tablename, idArray, callback) { 
    var resultsArray = []; 

    // Queue up all the async queries. 
    for (var id of idArray){ 
     queryTable(table, id, handleResponse); 
    } 

    // A query finished, so handle the result. 
    function handleResponse (error, results, fields) { 
     if (error) { 
      throw error; 
     } 

     // Add the query result to array of results. 
     resultsArray.push(results[0]); 

     // Check if all queries are done. 
     if (resultsArray.length === idArray.length) { 
      // Invoke the callback with the resultsArray. 
      // The callback is in fact the `displayData` function. 
      callback(resultsArray); 
     } 
    } 
} 

// Execute a query, using the `cb` callback to handle the response. 
function queryForeignTable (tablename, id, cb) { 
    var query = "SELECT * FROM " + tablename + " WHERE id=" + id; 
    connection.query(query, cb); 
} 

beachte, dass die handleResponse Funktion innerhalb des Schutzbereiches der readTable Funktion definiert ist, so dass er die Variablen in readTable s Umfang zugreifen kann, wie beispielsweise resultsArray und callback.

Hoffe, dass hilft.

Verwandte Themen