promiseを使用するための一般的なルールから始めましょう:
非同期で何かを行うすべての関数は、promiseを返す必要があります
あなたの場合、これらはどの機能ですか? getPrayerInCat
、forEach
コールバック、およびPrayer.find
。
うーん、Prayer.find
はpromiseを返しません。これはライブラリ関数であるため、変更できません。ルール2が機能します:
そうでないすべての関数の即時ラッパーを作成します
私たちの場合、Qのノードインターフェースヘルパーを使えば簡単です:
var find = Q.nbind(Prayer.find, Prayer);
今では約束しかないので、延期する必要はありません。 3番目のルールが機能します:
非同期の結果で何かを行うものはすべて
.then
に入ります コールバック
…そして結果を返します。地獄、その結果は、「何か」が非同期であった場合でも約束になる可能性があります!これで、完全なコールバック関数を書くことができます:
function getPrayerCount(data2) {
var id = data2.id;
return find({prayerCat:id})
// ^^^^^^ Rule 1
.then(function(prayer) {
// ^^^^^ Rule 3
if (!prayer)
data2.prayersCount = 0;
else
data2.prayersCount = prayer.length;
return data2;
// ^^^^^^ Rule 3b
});
}
さて、もう少し複雑なものがあります。それはループです。 getPrayerCount()
を繰り返し呼び出す 複数のpromiseを取得します。その非同期タスクは並行して実行され、不明な順序で解決されます。それらすべてを待ちたいのです。つまり、各タスクが終了したときにすべての結果で解決される約束を取得します。
このような複雑なタスクについては、独自の解決策を考え出そうとしないでください。
ライブラリのAPIを確認してください
そしてそこにQ.all
があります 、これはまさにこれを行います。 getPrayerInCat
を書く 今は簡単です:
function getPrayerInCat(data) {
var promises = data.map(getPrayerCount); // don't use forEach, we get something back
return Q.all(promises);
// ^^^^^^ Rule 1
}
Q.all
の配列で何かをする必要がある場合 解決するには、ルール3を適用するだけです。