Promise ve async/await, JavaScript'te asenkron işlemleri yönetmenin modern yollarıdır. Ancak hataları doğru şekilde ele almazsanız uygulamanız sessizce çökebilir veya kullanıcıya anlamsız hatalar gösterebilir. Bu yazıda, Promise ve async/await ile hata yönetiminde en sık karşılaşılan sorunları ve bunları çözmek için uygulanabilir ipuçlarını adım adım ele alacağız. Ayrıca, projelerinizde standart bir hata yönetimi yaklaşımı oluşturmanız için bir kontrol listesi sunacağız.
Promise'lerde Hata Yakalama: .catch() vs try/catch
Bir Promise zincirinde hataları yakalamak için iki ana yöntem vardır:
- Zincir sonunda .catch(): Tüm olası hataları tek bir noktada yakalar.
- Her .then() içinde try/catch: Daha granüler kontrol sağlar, ancak kod tekrarına yol açar.
Genel kural: Promise zincirinizin sonunda mutlaka bir .catch() bulundurun. Ara adımlarda hata dönüşümü yapmanız gerekiyorsa, .catch() içinde hatayı işleyip yeniden fırlatabilirsiniz. Örneğin:
fetch('/api/user')
.then(response => response.json())
.then(data => processUser(data))
.catch(error => {
console.error('Kullanıcı yüklenemedi:', error);
// Kullanıcıya gösterilecek bir hata döndür
return { error: 'Kullanıcı bilgisi alınamadı.' };
});Async/Await'te Hata Yönetimi: try/catch Blokları
Async fonksiyonlarda hataları yakalamak için try/catch kullanılır. Unutulmaması gereken en kritik nokta: await ile beklenen her Promise'in hata fırlatabileceği varsayımıyla hareket edin. Özellikle birden fazla await varsa, her birini ayrı try/catch bloklarına almak yerine, tüm işlemi kapsayan bir try/catch kullanmak çoğu durumda yeterlidir:
async function loadUserData(userId) {
try {
const user = await fetchUser(userId);
const posts = await fetchPosts(user.id);
return { user, posts };
} catch (error) {
console.error('Veri yüklenirken hata:', error);
throw new Error('Kullanıcı verisi alınamadı.');
}
}Fakat belirli bir adımda hata olursa farklı bir işlem yapılması gerekiyorsa, iç içe try/catch kullanmaktan kaçının; bunun yerine her işlemi ayrı bir yardımcı fonksiyona ayırın.
Yaygın Hatalar ve Çözümleri
- Unhandled Promise Rejection: Promise içinde yakalanmayan hatalar, Node.js ortamında sürecin çökmesine neden olabilir. Her zaman bir
.catch()ekleyin veya global birunhandledRejectionolay dinleyicisi kullanın. - Async fonksiyon içinde throw edilen hata: Bir async fonksiyonda
throwkullanırsanız, bu hata döndürülen Promise tarafından reddedilir. Bu durumda çağıran tarafın try/catch ile yakalaması gerekir. - Zincirde hata yutma:
.catch()içinde hiçbir şey yapmamak veya sadece loglamak, hatanın zinciri etkilemesini engellemez. Hatayı işleyip ya yeni bir değer döndürün ya da yeniden fırlatın.
Gelişmiş Hata Yönetimi Stratejileri
Granüler Loglama ve Kullanıcıya Uygun Mesajlar
Hata yönetiminin iki amacı vardır: geliştiriciye teknik detay sağlamak ve kullanıcıya anlamlı bir geri bildirim vermek. Bunun için catch bloklarında hem console.error hem de kullanıcı arayüzünde gösterilecek bir hata mesajı ayarlayın.
Hata Nesnelerini Zenginleştirme
Standart Error nesnesi genellikle yeterlidir, ancak daha fazla bağlam için özel hata sınıfları oluşturabilirsiniz. Örneğin:
class ApiError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
}
}Bu sayede hata türüne göre farklı aksiyonlar alabilirsiniz.
Promise.all ve Promise.allSettled Kullanımı
Birden fazla Promise'i paralel çalıştırırken, Promise.all bir hata durumunda tüm Promise'leri reddeder. Bunun yerine Promise.allSettled kullanarak her bir Promise'in sonucunu ayrı ayrı alabilir ve hata olanları işleyebilirsiniz.
Kontrol Listesi: Hata Yönetiminde Unutmamanız Gerekenler
- Her Promise zincirinin sonunda bir .catch() bulunuyor mu?
- Async fonksiyonlarda try/catch kullanılıyor mu?
- Yakalanan hatalar hem loglanıyor hem de kullanıcıya anlamlı bir mesaj olarak iletilmeye hazır mı?
- Global unhandledRejection olayı dinleniyor mu? (Node.js için)
- Prompt.all yerine gerektiğinde Promise.allSettled kullanılıyor mu?
- Hata nesneleri yeterli bağlamı (status code, hata kodu, vs.) içeriyor mu?
- İç içe try/catch kullanımından kaçınılıp, kod modüler hale getirilmiş mi?
- catch bloklarında hata yutulmuyor, ya işleniyor ya da yeniden fırlatılıyor mu?
Performans ve Paralel İşlemlerle İlgili İpuçları
Asenkron hataları yönetirken performansı da göz önünde bulundurun. Örneğin, ağır hesaplamaları veya yoğun veri işleme görevlerini Web Workers ile arka plana taşımak, ana iş parçacığını bloke etmez. Ayrıca, kullanıcı etkileşimlerinde hızlı yanıt için debounce ve throttle yöntemleriyle asenkron çağrıları kontrol altında tutun.
Bu konularla ilgili daha fazla bilgi için Web Workers ile JavaScript'te Arka Plan İşlemleri ve React'te Debounce ve Throttle Nasıl Uygulanır? yazılarını inceleyebilirsiniz.
Sonuç
Hata yönetimi, asenkron JavaScript projelerinin olmazsa olmazıdır. Bu ipuçlarını ve kontrol listesini projelerinize entegre ederek hem geliştirici deneyimini hem de kullanıcı memnuniyetini artırabilirsiniz. Unutmayın: Hataları yakalamak yetmez, onlardan öğrenin ve sistemi daha sağlam hale getirin.
Sık Sorulan Sorular
Promise'lerde hata yakalamak için .catch() mi yoksa try/catch mi kullanmalıyım?
İkisi de işe yarar. Promise zincirlerinde .catch() kullanmak daha yaygındır ancak async/await içinde try/catch daha okunabilirdir. Genellikle her ikisini de projenizde kullanabilirsiniz, önemli olan her senaryoda hatayı yakalamaktır.
Async fonksiyonlarda tüm await'leri tek bir try/catch bloğuna almak zararlı mı?
Hayır, genellikle uygun bir yaklaşımdır. Ancak her bir await'in farklı hata işleme stratejisi gerekiyorsa, her birini ayrı fonksiyonlara bölmek daha iyidir. Tek try/catch bloğu, kod tekrarını azaltır ve genel hata yönetimini basitleştirir.
Unhandled Promise Rejection hatasını nasıl önleyebilirim?
Her Promise zincirine .catch() ekleyerek veya async fonksiyonları try/catch ile sarmalayarak bu hatayı önleyebilirsiniz. Ayrıca Node.js'de process.on('unhandledRejection') olayını dinleyerek merkezi bir hata yönetimi de kurabilirsiniz.
Hata mesajlarını kullanıcı arayüzünde göstermenin en iyi yolu nedir?
Hata yakalandıktan sonra, kullanıcıya teknik detaylar yerine anlaşılır bir mesaj gösterin. Örneğin, 'Sunucuya bağlanılamadı' gibi. Aynı anda konsola teknik detayları loglayın. Bu sayede hem kullanıcı deneyimi iyileşir hem de hata ayıklama kolaylaşır.






