Promise'ler
Neden Bu Konu Önemli?
Önceki derste callback hell'i gördük: iç içe geçmiş, okunamaz, bakımı imkânsız callback piramitleri. JavaScript topluluğu yıllarca bu sorunla boğuştuktan sonra, ES6 (2015) ile birlikte Promise dile eklendi. Promise, asenkron programlamanın "aydınlanma çağı"dır.
Bir Promise, "şu an elimde sonuç yok ama ileride olacak" diyen bir nesnedir. Tıpkı bir restoranda verilen sıra numarası gibi: yemeğin henüz hazır değil ama elindeki numara, yemek hazır olduğunda seni bilgilendirecek bir söz (promise).
Bu derste Promise'lerin nasıl oluşturulduğunu, nasıl zincirlendiğini, hata yönetimini ve Promise.all, Promise.race gibi güçlü statik metotları öğreneceğiz.
Promise Nedir?
Promise, bir asenkron işlemin gelecekteki sonucunu temsil eden nesnedir. Üç durumda (state) bulunabilir:
Pending (Bekliyor): İşlem devam ediyor, sonuç henüz belli değil
Fulfilled (Başarılı): İşlem tamamlandı, bir değer döndü
Rejected (Başarısız): İşlem hata ile sonuçlandı
Bir Promise pending'den ya fulfilled'a ya da rejected'a geçer. Bu geçiş tek seferlik ve geri dönülemezdir. Fulfilled olan bir Promise tekrar rejected olamaz, veya tam tersi.
┌──── resolve(değer) ────→ FULFILLED (başarılı)
│
PENDING ─┤
│
└──── reject(hata) ──────→ REJECTED (başarısız)Analoji: Online Sipariş
Promise'i online alışveriş siparişi gibi düşün:
Sipariş verdin → Promise oluşturuldu (pending)
Kargo yola çıktı, teslim edildi → fulfilled (resolve)
Ürün stokta yok, iptal edildi → rejected (reject)
Sipariş verdikten sonra gidip başka işlerini yaparsın. Sonuç geldiğinde (başarılı veya başarısız) bilgilendirilirsin.
Promise Oluşturma
Promise, new Promise() constructor'ı ile oluşturulur. Constructor bir executor fonksiyonu alır. Bu fonksiyon iki parametre alır: resolve (başarı) ve reject (hata).
// Promise oluşturma — temel syntax
const siparisim = new Promise((resolve, reject) => {
// Asenkron iş burada yapılır
const stokVar = true;
if (stokVar) {
resolve("Ürün kargoya verildi!"); // Başarılı → fulfilled
} else {
reject(new Error("Ürün stokta yok")); // Başarısız → rejected
}
});Executor fonksiyonu hemen (senkron olarak) çalışır. Yani new Promise(...) satırına gelindiğinde, içindeki kod anında execute edilir. Asenkronluk, resolve veya reject çağrıldıktan sonra .then() ve .catch() handler'larının çalışmasında ortaya çıkar.
// Executor hemen çalışır — bunu anlamak önemli
console.log("1 - Promise öncesi");
const p = new Promise((resolve, reject) => {
console.log("2 - Executor çalışıyor (SENKRON!)");
resolve("done");
});
console.log("3 - Promise sonrası");
p.then((val) => {
console.log("4 - then çalışıyor:", val);
});
console.log("5 - Script sonu");
// Çıktı:
// 1 - Promise öncesi
// 2 - Executor çalışıyor (SENKRON!) ← Executor hemen çalıştı
// 3 - Promise sonrası
// 5 - Script sonu
// 4 - then çalışıyor: done ← then her zaman asenkron (microtask)Gerçekçi Bir Promise Örneği
// Veritabanı sorgusu simülasyonu
function kullaniciBul(id) {
return new Promise((resolve, reject) => {
console.log(`Kullanıcı #${id} aranıyor...`);
// Asenkron işlem simülasyonu (1 saniye)
setTimeout(() => {
const kullanicilar = {
1: { id: 1, ad: "Ahmet", email: "ahmet@ornek.com" },
2: { id: 2, ad: "Ayşe", email: "ayse@ornek.com" },
};
const kullanici = kullanicilar[id];
if (kullanici) {
resolve(kullanici); // Kullanıcı bulundu
} else {
reject(new Error(`Kullanıcı #${id} bulunamadı`)); // Hata
}
}, 1000);
});
}
// Kullanım
kullaniciBul(1); // Promise döner, sonucu then/catch ile alırızthen, catch, finally
Promise'in sonucunu almak için üç metot kullanılır:
.then() — Başarılı Sonuç
kullaniciBul(1)
.then((kullanici) => {
console.log("Bulundu:", kullanici.ad);
// then içinden bir değer dönersen, yeni bir Promise oluşur
return kullanici.email;
})
.then((email) => {
console.log("Email:", email);
});
// Çıktı:
// Kullanıcı #1 aranıyor...
// (1 saniye sonra)
// Bulundu: Ahmet
// Email: ahmet@ornek.com.then() iki parametre alabilir: birincisi onFulfilled, ikincisi onRejected. Ama pratikte ikinci parametre yerine .catch() kullanılır.
.catch() — Hata Yakalama
kullaniciBul(99)
.then((kullanici) => {
console.log("Bulundu:", kullanici.ad);
})
.catch((hata) => {
console.error("Hata yakalandı:", hata.message);
});
// Çıktı:
// Kullanıcı #99 aranıyor...
// (1 saniye sonra)
// Hata yakalandı: Kullanıcı #99 bulunamadı💡 İpucu:
.catch()sadecerejectedilen Promise'leri değil,.then()callback'leri içinde fırlatılan hataları da yakalar. Bu yüzden.then(onFulfilled, onRejected)yerine.then().catch()pattern'ı tercih edilir.
// .catch() then içindeki hataları da yakalar
Promise.resolve("veri")
.then((veri) => {
// then içinde bir hata oluşursa...
throw new Error("İşleme hatası!");
return veri.toUpperCase();
})
.catch((hata) => {
// ...catch onu yakalar!
console.error("Yakalandı:", hata.message);
});
// Çıktı: Yakalandı: İşleme hatası!.finally() — Her Durumda Çalışır
// finally: Başarılı da olsa, hatalı da olsa çalışır
// Loading spinner kapatmak, kaynakları temizlemek için idealdir
function veriCek(url) {
console.log("⏳ Yükleniyor...");
return fetch(url)
.then((response) => response.json())
.then((data) => {
console.log("✅ Veri geldi:", data);
return data;
})
.catch((hata) => {
console.error("❌ Hata:", hata.message);
})
.finally(() => {
console.log("🔄 Yükleme tamamlandı (başarılı veya değil)");
// Loading spinner burada kapatılır
});
}Promise Chaining (Zincirleme)
Promise'lerin en güçlü özelliklerinden biri zincirleme (chaining) yapabilmektir. Her .then() çağrısı yeni bir Promise döner. Bu sayede asenkron işlemler düz bir çizgi halinde yazılabilir — callback hell'deki piramit yapısı yerine.
Callback Hell vs Promise Chain
// ❌ Callback Hell — iç içe piramit
kullaniciyiGetir(1, (kullanici) => {
siparisleriGetir(kullanici.id, (siparisler) => {
urunDetayGetir(siparisler[0].urunId, (urun) => {
console.log(urun);
});
});
});
// ✅ Promise Chain — düz ve okunabilir
kullaniciyiGetir(1)
.then((kullanici) => siparisleriGetir(kullanici.id))
.then((siparisler) => urunDetayGetir(siparisler[0].urunId))
.then((urun) => console.log(urun))
.catch((hata) => console.error("Herhangi bir adımda hata:", hata));Zincirin güzelliği: herhangi bir adımda oluşan hata, en sondaki .catch()'e düşer. Her adım için ayrı hata yakalama yazmanıza gerek yok.
Chaining Derinlemesine
// Her then yeni bir Promise döner
// Döndürdüğün değer, sonraki then'e parametre olarak gelir
function siparisSureci(urunId) {
return stokKontrol(urunId)
.then((stok) => {
console.log(`Stok: ${stok.adet} adet`);
return odemeYap(urunId, stok.fiyat); // Promise döner
})
.then((odeme) => {
console.log(`Ödeme: ${odeme.tutar} TL — ${odeme.durum}`);
return kargoOlustur(urunId, odeme.id); // Promise döner
})
.then((kargo) => {
console.log(`Kargo: ${kargo.takipNo}`);
return emailGonder(kargo.takipNo); // Promise döner
})
.then(() => {
console.log("✅ Sipariş tamamlandı!");
})
.catch((hata) => {
// Zincirin HANGİ adımında hata olursa olsun buraya düşer
console.error("❌ Sipariş hatası:", hata.message);
});
}then İçinden Ne Dönebilirsin?
Promise.resolve(1)
// 1. Normal değer dönmek → otomatik Promise.resolve() ile sarılır
.then((val) => val * 2) // return 2
// 2. Promise dönmek → chain o Promise'i bekler
.then((val) => Promise.resolve(val + 10)) // return Promise<12>
// 3. Hata fırlatmak → otomatik Promise.reject() ile sarılır
.then((val) => {
if (val > 10) throw new Error("Çok büyük!");
return val;
})
// 4. Hiçbir şey dönmemek → undefined döner
.catch((hata) => {
console.log("Hata:", hata.message);
// catch'ten değer dönersen, chain devam eder (recover)
return 0; // Hata kurtarma — varsayılan değer
})
.then((val) => {
console.log("Son değer:", val); // 0
});💡 İpucu:
.catch()içinden bir değer döndürmek, hata kurtarma (error recovery) yapmak demektir. Chain kırılmaz, devam eder. Eğer hatanın yayılmasını istiyorsan,catchiçinden tekrarthrowyap.
Promise Hata Yönetimi Derinlemesine
Hata Yakalama Stratejileri
// Strateji 1: Zincirin sonunda tek catch (en yaygın)
getUser(1)
.then(getOrders)
.then(getLastOrder)
.catch((err) => {
// Herhangi bir adımdaki hata burada yakalanır
console.error("Genel hata:", err.message);
});
// Strateji 2: Her adımda özel hata yönetimi
getUser(1)
.catch((err) => {
// Sadece getUser hatasını yakalar
console.error("Kullanıcı hatası:", err.message);
return { id: 0, name: "Misafir" }; // Varsayılan kullanıcı
})
.then(getOrders)
.catch((err) => {
// Sadece getOrders hatasını yakalar
console.error("Sipariş hatası:", err.message);
return []; // Boş sipariş listesi
})
.then((orders) => {
console.log("Siparişler:", orders);
});Yakalanmamış Promise Hataları
// ⚠️ Tehlikeli: .catch() olmayan Promise
const tehlikeli = new Promise((resolve, reject) => {
reject(new Error("Bu hata yakalanmadı!"));
});
// .catch() yok → UnhandledPromiseRejection hatası
// Tarayıcıda ve Node.js'te bu olayı yakalayabilirsin:
// Tarayıcı
window.addEventListener("unhandledrejection", (event) => {
console.error("Yakalanmamış Promise hatası:", event.reason);
event.preventDefault(); // Varsayılan hatayı bastır
});
// Node.js
process.on("unhandledRejection", (reason, promise) => {
console.error("Yakalanmamış Promise hatası:", reason);
});⚠️ Dikkat: Her Promise chain'inin sonunda mutlaka
.catch()olmalıdır. Yakalanmamış Promise hataları, Node.js'in modern sürümlerinde programı sonlandırır. Tarayıcılarda da konsola hata basılır.
Promise Statik Metotları
Promise sınıfı, birden fazla Promise'i koordine etmek için çok güçlü statik metotlar sunar.
Promise.resolve() ve Promise.reject()
// Anında fulfilled bir Promise oluşturur
const basarili = Promise.resolve(42);
basarili.then((val) => console.log(val)); // 42
// Anında rejected bir Promise oluşturur
const basarisiz = Promise.reject(new Error("Hata!"));
basarisiz.catch((err) => console.error(err.message)); // Hata!
// Kullanım: Koşullu asenkron işlemler
function veriGetir(cache, key) {
// Cache'te varsa yeni bir fetch yapmaya gerek yok
if (cache.has(key)) {
return Promise.resolve(cache.get(key)); // Anında dön
}
// Yoksa API'den çek
return fetch(`/api/${key}`).then((r) => r.json());
}Promise.all() — Hepsi Başarılı Olmalı
Promise.all() bir Promise dizisi alır. Tamamı fulfilled olduğunda fulfilled olur. Herhangi biri rejected olursa, tamamı rejected olur.
// Promise.all — paralel çalıştırma
const kullanici = fetch("/api/user/1").then((r) => r.json());
const siparisler = fetch("/api/orders").then((r) => r.json());
const bildirimler = fetch("/api/notifications").then((r) => r.json());
// Üçü de paralel başlar, hepsi tamamlanınca sonuç gelir
Promise.all([kullanici, siparisler, bildirimler])
.then(([user, orders, notifs]) => {
// Destructuring ile her sonucu ayrı değişkene al
console.log("Kullanıcı:", user.name);
console.log("Sipariş sayısı:", orders.length);
console.log("Bildirim sayısı:", notifs.length);
})
.catch((hata) => {
// BİR TANESİ bile hata verirse buraya düşer
console.error("Bir şeyler yanlış gitti:", hata.message);
});// Promise.all ile pratik örnek: Birden fazla resim yükleme
function resimleriYukle(urlListesi) {
const yuklemeler = urlListesi.map((url) => {
return fetch(url).then((response) => {
if (!response.ok) throw new Error(`Yüklenemedi: ${url}`);
return response.blob();
});
});
return Promise.all(yuklemeler);
}
resimleriYukle([
"/img/banner.jpg",
"/img/logo.png",
"/img/avatar.jpg"
])
.then((bloblar) => {
console.log(`${bloblar.length} resim yüklendi`);
})
.catch((hata) => {
console.error("Yükleme hatası:", hata.message);
});💡 İpucu:
Promise.all"ya hep ya hiç" mantığıyla çalışır. 10 API çağrısından biri bile hata verirse tamamı başarısız sayılır. Eğer kısmi başarı yeterliysePromise.allSettledkullan.
Promise.allSettled() — Hepsini Bekle, Sonuçları Topla
ES2020'de eklenen allSettled, hiçbir zaman reject olmaz. Tüm Promise'ler tamamlanınca (ister fulfilled ister rejected), her birinin sonucunu bir dizi olarak verir.
// Promise.allSettled — kısmi başarı yeterli
const istekler = [
fetch("/api/products"), // ✅ Başarılı
fetch("/api/invalid-url"), // ❌ 404 — hata
fetch("/api/categories"), // ✅ Başarılı
];
Promise.allSettled(istekler)
.then((sonuclar) => {
sonuclar.forEach((sonuc, index) => {
if (sonuc.status === "fulfilled") {
console.log(`İstek ${index}: ✅ Başarılı`);
// sonuc.value → response nesnesi
} else {
console.log(`İstek ${index}: ❌ Hata — ${sonuc.reason}`);
// sonuc.reason → hata nesnesi
}
});
// Sadece başarılı olanları filtrele
const basarililar = sonuclar
.filter((s) => s.status === "fulfilled")
.map((s) => s.value);
console.log(`${basarililar.length}/${sonuclar.length} başarılı`);
});
// .catch() gerekmez — allSettled asla reject olmaz!Promise.race() — İlk Tamamlanan Kazanır
race, verilen Promise'lerden hangisi ilk tamamlanırsa (fulfilled veya rejected), onun sonucunu döner. Diğerleri çalışmaya devam eder ama sonuçları göz ardı edilir.
// Promise.race — timeout mekanizması oluşturma
function timeoutIle(promise, ms) {
const timeout = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(`İşlem ${ms}ms içinde tamamlanamadı`));
}, ms);
});
return Promise.race([promise, timeout]);
}
// Kullanım: API çağrısına 5 saniye timeout koy
timeoutIle(fetch("/api/slow-endpoint"), 5000)
.then((response) => {
console.log("Zamanında geldi!");
return response.json();
})
.catch((hata) => {
console.error(hata.message);
// "İşlem 5000ms içinde tamamlanamadı" veya fetch hatası
});// Promise.race — en hızlı CDN'i seçme
function enHizliCDN(url) {
const cdnler = [
fetch(`https://cdn1.example.com${url}`),
fetch(`https://cdn2.example.com${url}`),
fetch(`https://cdn3.example.com${url}`),
];
return Promise.race(cdnler);
}
enHizliCDN("/js/app.js")
.then((response) => {
console.log("En hızlı CDN yanıt verdi:", response.url);
});Promise.any() — İlk Başarılı Olan Kazanır
ES2021'de eklenen any, race'e benzer ama sadece fulfilled olanları dikkate alır. Rejected olanları atlar. Eğer hepsi rejected olursa, AggregateError fırlatır.
// Promise.any — ilk BAŞARILI olan
const kaynaklar = [
fetch("https://api1.example.com/data"), // ❌ Hata
fetch("https://api2.example.com/data"), // ❌ Hata
fetch("https://api3.example.com/data"), // ✅ Başarılı
];
Promise.any(kaynaklar)
.then((response) => {
console.log("Bir kaynak çalıştı:", response.url);
})
.catch((hata) => {
// AggregateError — hepsi başarısız olduğunda
console.error("Tüm kaynaklar çöktü!");
console.error("Hatalar:", hata.errors); // Tüm hataların dizisi
});Karşılaştırma Tablosu
// Promise.all → Hepsi başarılı → fulfilled | Biri hata → rejected
// Promise.allSettled → Her zaman fulfilled, tüm sonuçları verir
// Promise.race → İlk tamamlanan (başarılı VEYA hatalı) → sonucu döner
// Promise.any → İlk BAŞARILI olan → fulfilled | Hepsi hata → rejected
// Örnek: 3 Promise — ikisi başarılı, biri hatalı
const p1 = Promise.resolve("A");
const p2 = Promise.reject(new Error("Hata!"));
const p3 = Promise.resolve("C");
Promise.all([p1, p2, p3])
.catch((e) => console.log("all:", e.message));
// all: Hata! (biri hata → tamamı hata)
Promise.allSettled([p1, p2, p3])
.then((r) => console.log("allSettled:", r.map((x) => x.status)));
// allSettled: ["fulfilled", "rejected", "fulfilled"]
Promise.race([p1, p2, p3])
.then((r) => console.log("race:", r));
// race: A (ilk tamamlanan p1)
Promise.any([p1, p2, p3])
.then((r) => console.log("any:", r));
// any: A (ilk BAŞARILI olan p1)Promise Zincirleme İleri Seviye
Koşullu Zincirleme
Bazen chain'in ortasında bir koşula göre farklı yollar izlemek istersin:
function siparisOlustur(urunId, kullaniciId) {
return kullaniciyiDogrula(kullaniciId)
.then((kullanici) => {
if (kullanici.premiumUye) {
// Premium üyelere indirim uygula
return indirimliFiyatHesapla(urunId).then((fiyat) => ({
kullanici,
fiyat,
indirimli: true,
}));
}
// Normal fiyat
return normalFiyatHesapla(urunId).then((fiyat) => ({
kullanici,
fiyat,
indirimli: false,
}));
})
.then(({ kullanici, fiyat, indirimli }) => {
console.log(`${kullanici.ad}: ${fiyat} TL ${indirimli ? "(indirimli)" : ""}`);
return odemeBaslat(kullanici.id, fiyat);
})
.catch((hata) => {
console.error("Sipariş hatası:", hata.message);
});
}Sıralı vs Paralel İşlem
// ❌ SIRASAL — her istek öncekini bekler (yavaş!)
function sirasalGetir(idler) {
let sonuclar = [];
let chain = Promise.resolve();
idler.forEach((id) => {
chain = chain
.then(() => fetch(`/api/items/${id}`))
.then((r) => r.json())
.then((data) => {
sonuclar.push(data);
});
});
return chain.then(() => sonuclar);
}
// ✅ PARALEL — tüm istekler aynı anda başlar (hızlı!)
function paralelGetir(idler) {
const istekler = idler.map((id) =>
fetch(`/api/items/${id}`).then((r) => r.json())
);
return Promise.all(istekler);
}
// Performans farkı:
// 5 istek × 200ms = Sırasal: ~1000ms | Paralel: ~200msArray.reduce ile Sıralı Promise
Bazen sıralı çalıştırma gerekir (örn: her istek öncekinin sonucuna bağımlı):
// reduce ile sıralı Promise chain
const islemler = [
(onceki) => adim1(onceki),
(onceki) => adim2(onceki),
(onceki) => adim3(onceki),
];
islemler.reduce((chain, islem) => {
return chain.then(islem);
}, Promise.resolve("başlangıç"))
.then((sonuc) => console.log("Final:", sonuc));
// Pratik örnek: Dosyaları sırayla yükle (sunucu yükünü azaltmak için)
function dosyalariSiraylaYukle(dosyalar) {
return dosyalar.reduce((chain, dosya) => {
return chain.then((yuklenmisDosyalar) => {
return dosyaYukle(dosya).then((sonuc) => {
return [...yuklenmisDosyalar, sonuc];
});
});
}, Promise.resolve([]));
}Yaygın Hatalar ve Tuzaklar
Hata 1: Promise'i Döndürmeyi Unutmak
// ❌ Hata: then içinde Promise döndürülmemiş
function veriCekVeIsle() {
return fetch("/api/data")
.then((response) => {
response.json(); // return YOK! → undefined döner
})
.then((data) => {
console.log(data); // undefined — veri kayboldu!
});
}
// ✅ Doğrusu: return eklenmeli
function veriCekVeIsle() {
return fetch("/api/data")
.then((response) => {
return response.json(); // return ile Promise'i döndür
})
.then((data) => {
console.log(data); // Artık veri var
});
}
// 💡 Arrow function kısa syntax ile bu hata azalır:
function veriCekVeIsle() {
return fetch("/api/data")
.then((response) => response.json()) // implicit return
.then((data) => console.log(data));
}Hata 2: Promise İçinde Promise (Nesting)
// ❌ Hata: Promise chain yerine iç içe Promise
fetch("/api/user")
.then((response) => {
return response.json().then((user) => {
// İç içe then — callback hell'e geri dönüş!
return fetch(`/api/orders/${user.id}`).then((response) => {
return response.json().then((orders) => {
console.log(orders);
});
});
});
});
// ✅ Doğrusu: Düz chain
fetch("/api/user")
.then((response) => response.json())
.then((user) => fetch(`/api/orders/${user.id}`))
.then((response) => response.json())
.then((orders) => console.log(orders))
.catch((err) => console.error(err));Hata 3: catch Yerleşiminin Önemi
// catch'in yeri sonucu değiştirir!
// Senaryo 1: catch ORTADA — hata kurtarma yapar, chain devam eder
Promise.reject(new Error("Hata"))
.catch((err) => {
console.log("Yakalandı:", err.message);
return "kurtarma değeri"; // Chain devam eder
})
.then((val) => {
console.log("Devam:", val); // "Devam: kurtarma değeri"
});
// Senaryo 2: catch SONDA — hata yakalanır, chain biter
Promise.reject(new Error("Hata"))
.then((val) => {
console.log("Bu çalışmaz");
})
.catch((err) => {
console.log("Yakalandı:", err.message);
});Hata 4: Promise Constructor Anti-Pattern
// ❌ Anti-pattern: Gereksiz Promise constructor
function veriGetir() {
// fetch zaten Promise döner — tekrar sarmalamanın anlamı yok!
return new Promise((resolve, reject) => {
fetch("/api/data")
.then((response) => response.json())
.then((data) => resolve(data))
.catch((err) => reject(err));
});
}
// ✅ Doğrusu: Zaten Promise dönen fonksiyonu direkt kullan
function veriGetir() {
return fetch("/api/data")
.then((response) => response.json());
}Gerçek Dünya Örneği: Kullanıcı Dashboard'u
Tüm öğrendiklerimizi birleştiren kapsamlı bir örnek:
// Kullanıcı dashboard verilerini yükleme sistemi
class DashboardService {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.cache = new Map();
}
// Temel fetch wrapper — hata yönetimi ve cache
request(endpoint) {
// Cache kontrolü
if (this.cache.has(endpoint)) {
return Promise.resolve(this.cache.get(endpoint));
}
return fetch(`${this.baseUrl}${endpoint}`)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${endpoint}`);
}
return response.json();
})
.then((data) => {
this.cache.set(endpoint, data); // Cache'e kaydet
return data;
});
}
// Dashboard verilerini yükle
dashboardYukle(userId) {
console.log("📊 Dashboard yükleniyor...");
// Kullanıcı bilgisi MUTLAKA önce gelmeli
return this.request(`/users/${userId}`)
.then((kullanici) => {
console.log(`👤 Hoşgeldin, ${kullanici.ad}`);
// Kullanıcı geldikten sonra diğer veriler PARALEL yüklenebilir
return Promise.allSettled([
this.request(`/users/${userId}/orders`),
this.request(`/users/${userId}/notifications`),
this.request(`/users/${userId}/stats`),
this.request(`/users/${userId}/recommendations`),
]).then((sonuclar) => ({
kullanici,
siparisler: sonuclar[0].status === "fulfilled" ? sonuclar[0].value : [],
bildirimler: sonuclar[1].status === "fulfilled" ? sonuclar[1].value : [],
istatistikler: sonuclar[2].status === "fulfilled" ? sonuclar[2].value : null,
oneriler: sonuclar[3].status === "fulfilled" ? sonuclar[3].value : [],
}));
})
.then((dashboard) => {
console.log("✅ Dashboard hazır!");
console.log(`📦 ${dashboard.siparisler.length} sipariş`);
console.log(`🔔 ${dashboard.bildirimler.length} bildirim`);
return dashboard;
})
.catch((hata) => {
console.error("❌ Dashboard yüklenemedi:", hata.message);
// Kullanıcı verisi gelemediyse hiçbir şey gösterilemez
throw hata; // Hatayı yukarı fırlat
});
}
}
// Kullanım
const dashboard = new DashboardService("https://api.example.com");
dashboard.dashboardYukle(1)
.then((data) => renderDashboard(data))
.catch((err) => gosterHataSayfasi(err));Bu örnekte dikkat edilmesi gereken noktalar:
Kullanıcı bilgisi sıralı (diğer istekler ona bağımlı)
Siparişler, bildirimler, istatistikler, öneriler paralel (birbirinden bağımsız)
allSettledkullanarak kısmi hataları tolere ediyoruz (öneriler gelmese de dashboard gösterilebilir)Cache mekanizması ile tekrar eden istekler engelleniyor
Özet
Bu derste Promise'lerin tüm yönlerini öğrendik:
Promise üç durumda bulunur: pending, fulfilled, rejected. Geçiş tek seferlik ve geri dönülemezdir.
`.then()` başarılı sonucu, `.catch()` hatayı, `.finally()` her durumda çalışan kodu işler.
Promise chaining callback hell'i düz, okunabilir zincirlerle çözer. Her
.then()yeni bir Promise döner.`Promise.all` hepsi başarılı olmalı, `allSettled` hepsini bekler, `race` ilk tamamlanan, `any` ilk başarılı olan.
theniçinden return yapmayı unutmak en yaygın hatadır. Arrow function kısa syntax bu riski azaltır.Zaten Promise döndüren bir fonksiyonu
new Promise()ile sarmak anti-pattern'dır.
Bir sonraki derste, Promise chain'lerini daha da okunabilir yapan async/await syntax'ını öğreneceğiz.
AI Asistan
Sorularını yanıtlamaya hazır