Existuje několik návrhových vzorů, které můžete v node.js použít ke spouštění sekvenčních asynchronních operací. Ve všech z nich nemůžete spustit úzkou smyčku a čekat, až se něco stane – musíte nechat běžet jediné vlákno Javascriptu v node.js a dát mu co nejvíce cyklů.
Ruční iterace
Vložte kód pro iteraci do místní funkce (obvykle to nazývám next()
) a poté, když jedna iterace zavolá funkci posledního dokončení, můžete zavolat next()
znovu pro zahájení další iterace. Operaci můžete dokončit buď otestováním nějaké podmínky a nevoláním next()
pokud jsou věci hotové nebo první řádky next()
můžete vyzkoušet, zda jste hotovi.
Podívejte se na příklad kódu níže, jak by váš kód vypadal s ruční iterací.
Sekvenční sliby
Pokud pro asynchronní operace používáte přísliby, můžete nechat zřetězené přísliby, aby za vás udělaly všechny sekvence, jako v p().then(f1).then(f2).then(f3)
. Příklad toho můžete vidět v této odpovědi:Sliby jako async.each
.
Použijte asynchronní modul
modul Async podporuje řadu funkcí asynchronní správy. Mnozí to považují za velmi užitečné – jiní by k řešení podobných problémů raději použili sliby. V každém případě má řadu různých funkcí pro sekvenování. Pokud byste například chtěli pole iterovat asynchronně, použili byste něco takového:
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() {
//...
});
Zde je verze vašeho kódu, která provádí ruční iteraci pomocí vlastního next()
iterační funkce.
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
});
});
}
}
});
}