Der er et par designmønstre, du kan bruge i node.js til at køre sekventielle asynkrone operationer. I dem alle kan du ikke køre en stram løkke og vente på, at der sker noget - du skal lade den enkelte Javascript-tråd i node.js køre og give den så mange cyklusser som muligt.
Manuel gentagelse
Indsæt koden til en iteration i en lokal funktion (jeg plejer at kalde den next()
), og når en iteration kalder dens sidste fuldførelsesfunktion, kan du kalde next()
igen for at starte den næste iteration. Du kan afslutte operationen enten ved at teste en tilstand og ikke kalde next()
hvis tingene er gjort eller de første linjer i next()
kan teste for at se, om du er færdig.
Se kodeeksemplet nedenfor for, hvordan din kode vil se ud med manuel iteration.
Rækkefølgeløfter
Hvis du bruger løfter til dine asynkrone operationer, så kan du lade kædede løfter udføre al din sekventering for dig som i p().then(f1).then(f2).then(f3)
. Du kan se et eksempel på det i dette svar:Løfter som async.each
.
Brug Async-modulet
Async-modulet understøtter en række asynkronstyringsfunktioner. Mange finder det meget nyttigt – andre vil foretrække at bruge løfter til at løse lignende problemer. Under alle omstændigheder har den en række forskellige funktioner til sekventering. Hvis du for eksempel ville iterere et array asynkront, ville du bruge noget som dette:
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() {
//...
});
Her er en version af din kode, der udfører den manuelle iteration ved hjælp af en brugerdefineret next()
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
});
});
}
}
});
}