Il existe quelques modèles de conception que vous pouvez utiliser dans node.js pour exécuter des opérations asynchrones séquentielles. Dans chacun d'eux, vous ne pouvez pas exécuter une boucle serrée en attendant que quelque chose se produise - vous devez laisser le thread Javascript unique dans node.js s'exécuter et lui donner autant de cycles que possible.
Itération manuelle
Mettez le code d'une itération dans une fonction locale (je l'appelle généralement next()
) puis lorsqu'une itération appelle sa dernière fonction de complétion, vous pouvez appeler next()
à nouveau pour commencer la prochaine itération. Vous pouvez terminer l'opération en testant une condition et en n'appelant pas next()
si les choses sont faites ou les premières lignes de next()
peut tester pour voir si vous avez terminé.
Consultez l'exemple de code ci-dessous pour savoir à quoi ressemblerait votre code avec une itération manuelle.
Promesses de séquence
Si vous utilisez des promesses pour vos opérations asynchrones, vous pouvez laisser les promesses chaînées faire tout votre séquencement pour vous comme dans p().then(f1).then(f2).then(f3)
. Vous pouvez en voir un exemple dans cette réponse :Des promesses comme async.each
.
Utiliser le module asynchrone
Le Module asynchrone prend en charge un certain nombre de fonctions de gestion asynchrone. Beaucoup le trouvent très utile - d'autres préféreraient utiliser des promesses pour résoudre des problèmes similaires. Dans tous les cas, il a un certain nombre de fonctions différentes pour le séquençage. Par exemple, si vous vouliez itérer un tableau de manière asynchrone, vous utiliseriez quelque chose comme ceci :
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() {
//...
});
Voici une version de votre code qui effectue l'itération manuelle à l'aide d'un next()
personnalisé fonction d'itération.
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
});
});
}
}
});
}