Hallo dedlfix,
Laut Doku wartet conn.end(), bis alle Queries erledigt sind und gibt die Connection dann erst frei. Führt man mehrere Queries in Folge aus, wäre es vermutlich sinnvoll, selbst zu warten. Das macht es auch einfacher, noch Queries zwischenzuschieben, weil man dann nicht aufpassen muss das .end() zu verschieben. Im Fall der Nutzung eines Connection-Pools verwendet man nicht .end sondern .release, da ist es so, dass die Beispiele den release-Aufruf im Callback der Query zeigen und NICHT erwähnen, dass release() bis zum Ende laufender Queries wartet. Man sollte das also so übernehmen.
Eine korrekte, auf den Connection Pool gestützte Sequenzierung müsste wohl so aussehen (mal abgesehen davon, dass sich diese Aufgabe durch INSERT ON DUPLICATE KEY UPDATE besser lösen ließe - es geht mir um die Sequenzierung). Das Freigeben der Connection gehört in einen finally-Block.
function storeStuff(keyThingy, fooValue, barValue) {
var connection = null;
var needInsert = false;
return pool.getConnection()
.then(function(conn) {
connection = conn;
return connection.query("SELECT thingy FROM stuff WHERE thingy = ?", [keyThingy]);
})
.then(function(rows) {
needInsert = (rows.length === 0);
if (needInsert)
return connection.query("INSERT INTO stuff (thingy, foo, bar) VALUES(?,?,?)",
[ keyThingy, fooValue, barValue ]);
else
return connection.query("UPDATE stuff SET foo=?, bar=? WHERE thingy=?",
[ fooValue, barValue, keyThingy ]);
})
.then(function(result) {
return result.affectedRows;
})
.finally(function() {
if (connection)
connection.release();
});
}
Den Handler des letzten .then habe ich so geschrieben, dass er die Anzahl der geänderten Zeilen zurückgibt. Dieser Wert kann im weiteren Verlauf der Promise-Kette verwendet werden. Ein .catch ist in storeStuff nicht drin, ein Error wird durchgereicht.
.finally ist so etwas ähnliches wie then, es wird aber im Erfolgs- UND im Fehlerfall aufgerufen. Hinzu kommt die Besonderheit, dass die finally-Funktion das letzte Result der then-Kette weder bekommt noch ändern kann. Das ist hier ganz praktisch, sonst müsste man dafür sorgen, das Ergebnis der thens durchzuschleifen. Aber auch .finally gibt ein Promise zurück, man kann sich also hinten anhängen und die Ergebnisse weiter verarbeiten.
Genau dieses Promise gebe ich aus der storeStuff-Funktion zurück, d.h. man kann die Promise-Technik verwenden um das Ergebnis der darin ablaufenden Aktivitäten per Promise weiterzuverarbeiten. Wenn eine Query fehlschlägt wird der then nicht ausgeführt.
storeStuff(17, "fup", "bup")
.then(function(affected) {
console.log("Stuffed, " + affected + " records affected");
})
.catch(function(err) {
console.log("storeStuff failed, " + err);
});
Der Vorteil von Promises ist größtenteils optischer Natur.
Den „kleineren“ Teil habe ich hier mal präsentiert: Einfaches Verketten von Aktionen, sogar über Funktionsgrenzen hinweg. Mach das mal mit Callbacks, da musst Du das in jedem Callback speziell vorsehen.
Rolf
sumpsi - posui - clusi