node.jsでシーケンシャル非同期操作を実行するために使用できるデザインパターンがいくつかあります。それらすべてにおいて、何かが起こるのを待つタイトなループを実行することはできません。node.jsの単一のJavascriptスレッドを実行させ、可能な限り多くのサイクルを与える必要があります。
手動反復
反復のコードをローカル関数に配置します(通常はnext()
と呼びます )そして、1回の反復で最後の完了関数を呼び出すときに、next()
を呼び出すことができます。 もう一度、次の反復を開始します。いくつかの条件をテストし、next()
を呼び出さないことで、操作を終了できます。 処理が完了した場合、またはnext()
の最初の行 完了したかどうかをテストできます。
手動反復でコードがどのように見えるかについては、以下のコード例を参照してください。
シーケンスの約束
非同期操作にpromiseを使用する場合は、p().then(f1).then(f2).then(f3)
のように、連鎖promiseにすべてのシーケンス処理を実行させることができます。 。この回答でその例を見ることができます:async.eachのような約束
。
非同期モジュールを使用する
非同期モジュール 多数の非同期管理機能をサポートします。多くの人がそれが非常に役立つと感じています-他の人は同様の問題を解決するために約束を使うことを好むでしょう。いずれにせよ、それはシーケンスのための多くの異なる機能を持っています。たとえば、配列を非同期で反復する場合は、次のように使用します。
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() {
//...
});
これは、カスタムのnext()
を使用して手動で反復するコードのバージョンです。 反復関数。
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
});
});
}
}
});
}