[NODE JS] Promise.allSettled ile Tum Sonuclari Alma
Merhaba arkadaslar, bir onceki konuda Promise.all'in fail-fast davranis sergiledigini soylemistim. Yani bir Promise bile reject olsa tum islem iptal oluyordu. Peki ya her Promise'in sonucunu, basarili olsun ya da olmasin, almak isterseniz ne olacak? Iste Promise.allSettled tam bu is icin tasarlanmis. ES2020 ile gelen bu fonksiyon, production'da cok ise yariyor.
allSettled vs all
Promise.allSettled, tum Promise'lerin sonuclanmasini (resolve veya reject farketmez) bekler ve her birinin sonucunu ayri ayri raporlar. Donen dizideki her eleman bir nesne: ya { status: 'fulfilled', value: sonuc } ya da { status: 'rejected', reason: hata }. Bu sayede hangi islemlerin basarili hangilerinin basarisiz oldugunu tek tek gorebilirsiniz.
Ben bu fonksiyonu ozellikle toplu islemlerde kullaniyorum. Mesela 100 kullaniciya bildirim gondermem gerekiyor. Promise.all kullansam, bir kullanicinin bildirimi basarisiz olsa geri kalan 99'unun sonucunu goremem. allSettled ile hepsinin sonucunu alip, basarisiz olanlari ayri ele alabilirim. Gercek hayatta tam ihtiyac bu.
JavaScript:
// Promise.allSettled temel kullanim
async function temelOrnek() {
const gorevler = [
Promise.resolve('Basarili 1'),
Promise.reject(new Error('Hata 1')),
Promise.resolve('Basarili 2'),
Promise.reject(new Error('Hata 2')),
Promise.resolve('Basarili 3')
];
const sonuclar = await Promise.allSettled(gorevler);
console.log('=== Tum Sonuclar ===');
sonuclar.forEach((sonuc, index) => {
if (sonuc.status === 'fulfilled') {
console.log(` Gorev ${index + 1}: BASARILI - ${sonuc.value}`);
} else {
console.log(` Gorev ${index + 1}: BASARISIZ - ${sonuc.reason.message}`);
}
});
// Basarili ve basarisiz olanlari ayir
const basarililar = sonuclar.filter(s => s.status === 'fulfilled');
const basarisizlar = sonuclar.filter(s => s.status === 'rejected');
console.log(`\nBasarili: ${basarililar.length}, Basarisiz: ${basarisizlar.length}`);
}
temelOrnek();
// Gercek hayat ornegi: Toplu bildirim gonderimi
async function topluBildirimGonder(kullanicilar, mesaj) {
const bildirimIslemleri = kullanicilar.map(kullanici =>
bildirimGonder(kullanici, mesaj)
);
const sonuclar = await Promise.allSettled(bildirimIslemleri);
const rapor = {
toplam: sonuclar.length,
basarili: 0,
basarisiz: 0,
hatalar: []
};
sonuclar.forEach((sonuc, index) => {
if (sonuc.status === 'fulfilled') {
rapor.basarili++;
} else {
rapor.basarisiz++;
rapor.hatalar.push({
kullanici: kullanicilar[index].ad,
hata: sonuc.reason.message
});
}
});
console.log(`\n=== Bildirim Raporu ===`);
console.log(`Toplam: ${rapor.toplam}`);
console.log(`Basarili: ${rapor.basarili}`);
console.log(`Basarisiz: ${rapor.basarisiz}`);
if (rapor.hatalar.length > 0) {
console.log('\nHatalar:');
rapor.hatalar.forEach(h => {
console.log(` - ${h.kullanici}: ${h.hata}`);
});
}
return rapor;
}
// Bildirim gonderme simulasyonu
function bildirimGonder(kullanici, mesaj) {
return new Promise((resolve, reject) => {
setTimeout(() => {
// Rastgele basarisizlik simule et
if (Math.random() < 0.3) {
reject(new Error(`${kullanici.ad} icin gonderim basarisiz`));
} else {
resolve({ kullaniciId: kullanici.id, durum: 'gonderildi' });
}
}, Math.random() * 200);
});
}
// Kullanim
const kullaniciListesi = [
{ id: 1, ad: 'Ahmet' },
{ id: 2, ad: 'Ayse' },
{ id: 3, ad: 'Mehmet' },
{ id: 4, ad: 'Fatma' },
{ id: 5, ad: 'Ali' }
];
topluBildirimGonder(kullaniciListesi, 'Merhaba!');
Retry Mekanizmasi ile Birlikte Kullanim
allSettled'in guclu bir kullanim alani da retry mekanizmasiyla birlikte calismaktir. Ilk turda basarisiz olanlari tespit edip, sadece onlari tekrar deneyebilirsiniz. Bu yaklasim ozellikle dis servislere yapilan toplu API cagrilarinda cok ise yarar.
JavaScript:
// Retry mekanizmali toplu islem
async function retryliTopluIslem(islemler, maxDeneme = 3) {
let kalanIslemler = islemler.map((islem, index) => ({ index, islem }));
const tumSonuclar = new Array(islemler.length);
let deneme = 0;
while (kalanIslemler.length > 0 && deneme < maxDeneme) {
deneme++;
console.log(`\nDeneme ${deneme}/${maxDeneme} - ${kalanIslemler.length} islem...`);
const sonuclar = await Promise.allSettled(
kalanIslemler.map(item => item.islem())
);
const yeniKalan = [];
sonuclar.forEach((sonuc, i) => {
const orijinalIndex = kalanIslemler[i].index;
if (sonuc.status === 'fulfilled') {
tumSonuclar[orijinalIndex] = { basarili: true, deger: sonuc.value, deneme };
} else if (deneme < maxDeneme) {
yeniKalan.push(kalanIslemler[i]);
} else {
tumSonuclar[orijinalIndex] = { basarili: false, hata: sonuc.reason.message, deneme };
}
});
kalanIslemler = yeniKalan;
}
return tumSonuclar;
}
// Kullanim
async function main() {
let cagriSayisi = 0;
const islemler = Array.from({ length: 10 }, (_, i) => {
return () => new Promise((resolve, reject) => {
cagriSayisi++;
setTimeout(() => {
// Her denemede basari sansi artiyor
if (Math.random() < 0.6) {
resolve(`Islem ${i + 1} basarili`);
} else {
reject(new Error(`Islem ${i + 1} basarisiz`));
}
}, 50);
});
});
const sonuclar = await retryliTopluIslem(islemler, 3);
console.log('\n=== Final Rapor ===');
sonuclar.forEach((s, i) => {
const durum = s.basarili ? 'OK' : 'FAIL';
console.log(` Islem ${i + 1}: ${durum} (deneme: ${s.deneme})`);
});
console.log(`\nToplam API cagrisi: ${cagriSayisi}`);
}
main().catch(console.error);
Ne Zaman allSettled, Ne Zaman all?
Tecrubeme gore su duruma gore karar verin: Eger tum islemlerin basarili olmasi zorunluysa (ornegin bir transaction'in tum adimlari) Promise.all kullanin. Eger islemler birbirinden bagimsiz ve kismini basarisizlik kabul edilebilirse Promise.allSettled kullanin. Toplu e-posta gonderimi, coklu API veri toplama, health check gibi islemlerde allSettled daha mantikli. Odeme islemi, veritabani migration gibi islemlerde all kullanin.
allSettled olmadan once insanlar benzer davranisi elde etmek icin her Promise'i catch ile sarip hatayı degere donusturuyorlardi. Ama bu hem cikkin hem de error bilgisini kaybetme riski tasiyordu. allSettled bu sorunu kokeninden cozdü. Hadi sonraki konuya gecelim, Promise.race sizi bekliyor!
Emeğiniz ve katkınız için teşekkür ederiz!
Konunuz gerekli incelemelerden geçerek onaylandı. Topluluğumuza katkılarınızın devamını bekliyoruz.
İyi forumlar!
Konunuz gerekli incelemelerden geçerek onaylandı. Topluluğumuza katkılarınızın devamını bekliyoruz.
İyi forumlar!

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)
Benzer konular
- Cevaplar
- 0
- Görüntüleme
- 999
- Cevaplar
- 3
- Görüntüleme
- 1K
- Cevaplar
- 1
- Görüntüleme
- 451
- Cevaplar
- 3
- Görüntüleme
- 486
- Kilitli
- Cevaplar
- 4
- Görüntüleme
- 2K