Mari kita mulai dengan aturan umum untuk menggunakan janji:
Setiap fungsi yang melakukan sesuatu yang tidak sinkron harus mengembalikan janji
Fungsi mana yang ada dalam kasus Anda? Ini getPrayerInCat
, forEach
panggilan balik, dan Prayer.find
.
Hm, Prayer.find
tidak mengembalikan janji, dan ini adalah fungsi perpustakaan sehingga kami tidak dapat mengubahnya. Aturan 2 mulai berlaku:
Buat pembungkus langsung untuk setiap fungsi yang tidak
Dalam kasus kami, itu mudah dengan bantuan antarmuka simpul Q:
var find = Q.nbind(Prayer.find, Prayer);
Sekarang kami hanya memiliki janji, dan tidak lagi membutuhkan penundaan. Aturan ketiga mulai berlaku:
Semua yang melakukan sesuatu dengan hasil asinkron masuk ke
.then
panggilan balik
…dan mengembalikan hasilnya. Sial, hasil itu bahkan bisa menjadi janji jika "sesuatu" tidak sinkron! Dengan ini, kita dapat menulis fungsi panggilan balik yang lengkap:
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
});
}
Sekarang, kita memiliki sesuatu yang sedikit lebih rumit:sebuah loop. Berulang kali memanggil getPrayerCount()
akan memberi kita banyak janji, yang tugas asinkronnya berjalan secara paralel dan diselesaikan dalam urutan yang tidak diketahui. Kami ingin menunggu semuanya - yaitu, dapatkan janji yang diselesaikan dengan semua hasil saat setiap tugas selesai.
Untuk tugas-tugas rumit seperti itu, jangan mencoba untuk menemukan solusi Anda sendiri:
Periksa API perpustakaan Anda
Dan di sana kita menemukan Q.all
, yang melakukan hal ini. Menulis getPrayerInCat
sangat mudah sekarang:
function getPrayerInCat(data) {
var promises = data.map(getPrayerCount); // don't use forEach, we get something back
return Q.all(promises);
// ^^^^^^ Rule 1
}
Jika kita perlu melakukan sesuatu dengan larik yang Q.all
memutuskan untuk, cukup terapkan Aturan 3.