Es gibt einige Entwurfsmuster, die Sie in node.js verwenden können, um sequenzielle asynchrone Vorgänge auszuführen. In allen können Sie keine enge Schleife laufen lassen und darauf warten, dass etwas passiert – Sie müssen den einzelnen Javascript-Thread in node.js laufen lassen und ihm so viele Zyklen wie möglich geben.
Manuelle Iteration
Fügen Sie den Code für eine Iteration in eine lokale Funktion ein (ich nenne sie normalerweise next()
) und dann, wenn eine Iteration ihre letzte Abschlussfunktion aufruft, können Sie next()
aufrufen erneut, um die nächste Iteration zu starten. Sie können die Operation beenden, indem Sie entweder eine Bedingung testen und next()
nicht aufrufen ob Dinge erledigt sind oder die ersten Zeilen von next()
können testen, ob Sie fertig sind.
Sehen Sie sich das Codebeispiel unten an, um zu sehen, wie Ihr Code mit manueller Iteration aussehen würde.
Sequence Promises
Wenn Sie Promises für Ihre asynchronen Operationen verwenden, können Sie verkettete Promises die gesamte Sequenzierung für Sie erledigen lassen, wie in p().then(f1).then(f2).then(f3)
. Ein Beispiel dafür finden Sie in dieser Antwort:Versprechen wie async.each
.
Verwenden Sie das Async-Modul
Das Async-Modul unterstützt eine Reihe von asynchronen Verwaltungsfunktionen. Viele finden es sehr nützlich – andere würden lieber Versprechungen verwenden, um ähnliche Probleme zu lösen. In jedem Fall hat es eine Reihe verschiedener Funktionen für die Sequenzierung. Wenn Sie beispielsweise ein Array asynchron iterieren möchten, würden Sie Folgendes verwenden:
async.eachSeries(hugeArray, function iterator(item, callback) {
if (inCache(item)) {
callback(null, cache[item]); // if many items are cached, you'll overflow
} else {
doSomeIO(item, callback);
}
}, function done() {
//...
});
Hier ist eine Version Ihres Codes, die die manuelle Iteration mit einem benutzerdefinierten next()
durchführt Iterationsfunktion.
function runQuery(callback) {
mysql.getConnection(function(err, connection) {
if (err) {
connection.release();
callback(err);
return;
}
var array = [];
var count = 10;
var index = 0;
function next() {
if (index++ < count) {
array.push([index, 'master']);
console.log('100-elements');
connection.beginTransaction(function(err) {
if (err) {
// can't throw here in an async function
// use callback to communicate error
callback(err);
return;
}
var query = "insert into users(username, password) values ?";
connection.query(query, [array], function(err, rows) {
if (!err) {
//commit start
connection.commit(function() {
if (err) {
console.error(err);
connection.rollback(function() {
console.error('rollback error');
callback(err);
return;
});
} else {
console.log("Commit");
// now do the next iteration
next();
} // if err
}); //commit end
} else {
console.log(err);
connection.rollback(function() {
callback(err);
return;
});
} // if
});
});
}
}
});
}