Async/await, JavaScript'te asenkron işlemleri senkron gibi yazmayı sağlayan modern bir yöntemdir. Ancak yanlış hata yönetimi, uygulamalarda sessiz hatalara veya beklenmedik çökmelere yol açabilir. Bu yazıda, async/await ile hata yönetiminin temel yollarını – try-catch, promise.catch ve global yakalama – karşılaştırmalı olarak ele alıyoruz. Ayrıca pratik ipuçları ve sık yapılan hatalara değiniyoruz.
Async/Await Hatalarının Temel Yapısı
Async fonksiyonlar her zaman bir Promise döndürür. await ifadesi, bir Promise'in çözülmesini beklerken, reddedilirse bir istisna fırlatır. Bu istisna, fonksiyon içinde try-catch ile yakalanmazsa, fonksiyonun döndürdüğü Promise reddedilir. Bu nedenle hata yönetimi, async/await kullanımının ayrılmaz bir parçasıdır.
Try-Catch ile Hata Yakalama
En yaygın yöntem, await ifadelerini bir try-catch bloğu içine almaktır. Bu, hataları doğrudan fonksiyon içinde yönetmenize olanak tanır. Örneğin:
async function getData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Veri çekilirken hata:', error);
throw error; // hatayı yukarı iletmek istiyorsanız
}
}
Try-catch, hata yakalama akışını net bir şekilde gösterir, ancak her await için ayrı try-catch yazmak kod tekrarına yol açabilir. Bu durumda, REST API'lerde Etkili Hata Yönetimi yazısındaki standart HTTP durum kodları yaklaşımını benzer bir mantıkla uygulayabilirsiniz.
Kısmi Hata Yönetimi
Bazen yalnızca belirli await ifadelerinin hatalarını yakalamak isteyebilirsiniz. Bu durumda, try-catch'i yalnızca ilgili await'in etrafına yerleştirin. Diğer hatalar fonksiyonun dışına yayılır.
Promise.catch Kullanımı
Async fonksiyon bir Promise döndürdüğü için, fonksiyonu çağıran kod .catch() ile hatayı yakalayabilir:
getData()
.then(data => console.log(data))
.catch(error => console.error('Hata:', error));
Bu yöntem, fonksiyonun kendi içinde hata yönetimi yapmaz; tüm sorumluluğu çağırana bırakır. Özellikle hataların merkezi bir yerde işlenmesi istendiğinde tercih edilir. Ancak, fonksiyon içinde birden fazla await varsa ve her birinin hatası farklı şekilde işlenecekse, tek bir .catch() yetersiz kalabilir.
Hata Sınırları ve Global Hata Yakalama
Async fonksiyonlarda yakalanmayan herhangi bir hata, prosesi çökertebilir (Node.js) veya tarayıcıda konsola düşer. Bu nedenle, en üst seviyede bir hata yönetimi katmanı oluşturmak kritiktir. Node.js'de process.on('unhandledRejection') ile, tarayıcıda ise window.onunhandledrejection ile global hataları yakalayabilirsiniz.
Özellikle büyük projelerde, REST API'lerde Veri Doğrulama ve Şema Validasyonu gibi konularda olduğu gibi, hata yönetimini standartlaştırmak faydalıdır.
Try-Catch vs Promise.catch Karşılaştırması
| Özellik | Try-Catch (İç Yönetim) | Promise.catch (Dış Yönetim) |
|---|---|---|
| Kapsam | Fonksiyon içindeki await'leri kapsar | Tüm async fonksiyon çağrısını kapsar |
| Hata İşleme Yeri | Fonksiyon içinde, isteğe bağlı olarak | Çağıran tarafta, merkezi olarak |
| Karmaşık Akışlar | Her await için ayrı blok gerekebilir | Tek bir .catch() tüm hataları toplar |
| Hata Türüne Göre Ayırma | Catch bloğunda error türü kontrol edilir | Promise zinciri ile birden çok .catch() eklenebilir |
Sık Yapılan Hatalar ve Çözümleri
- Hataları susmak (swallow): Catch bloğunda error log'lamak yerine hiçbir şey yapmamak. Hatanın kaynağını bulmayı zorlaştırır. Her zaman hatayı en azından konsola yazdırın veya bir hata raporlama servisine gönderin.
- Tüm hataları aynı şekilde işlemek: Her hata aynı türde olmayabilir (network hatası, JSON ayrıştırma hatası, vb.). Hatayı analiz edip uygun işlemi yapın.
- Try-catch içinde return veya throw kullanmamak: Catch bloğundan sonra akışı doğru yönlendirmek için return veya throw kullanın. Eğer hata düzeltildiyse devam, düzeltilemiyorsa yukarı fırlatın.
- Async olmayan callback'lerde hata yakalamak: Array.forEach gibi senkron callback'lerde try-catch içinde await kullanmak hatayı yakalamaz; çünkü forEach async değildir. Bunun yerine for...of döngüsü veya Promise.all kullanın.
Pratik İpuçları
- Async fonksiyonların dönüş değerini her zaman await ile almayın; gereksiz beklemelerden kaçının.
- Çok sayıda async işlem varsa, Promise.allSettled() kullanarak tüm hataları toplu olarak yönetin.
- Hata nesnelerine anlamlı mesajlar ve hata kodları ekleyin; böylece hata ayıklama kolaylaşır.
- Global hata yakalayıcıları yalnızca gerçekten beklenmeyen durumlar için kullanın, normal akışın parçası olarak tasarlamayın.
Async/await ile hata yönetimi, JavaScript'te sağlam uygulamalar geliştirmenin temelidir. Try-catch ve promise.catch arasında seçim yaparken, kodun okunabilirliğini ve bakımını göz önünde bulundurun. Küçük projelerde try-catch daha doğrudan iken, büyük projelerde merkezi hata yönetimi için promise.catch ve global yakalayıcılar daha uygundur. Unutmayın, hataları yönetmek onları gizlemek değil, kullanıcıya ve geliştiriciye anlamlı geri bildirim sağlamaktır.
Sık Sorulan Sorular
Async/await'te try-catch mi yoksa promise.catch mi daha iyidir?
Her iki yöntemin de kullanım yeri farklıdır. Try-catch, fonksiyon içindeki hataları yerel olarak yönetmek için idealdir; kodun okunabilirliğini artırır. Promise.catch ise hataları çağıran tarafta merkezi olarak işlemek istediğinizde tercih edilir. Büyük projelerde genellikle promise.catch ile global bir hata yönetimi katmanı oluşturmak daha sürdürülebilir olur.
Async fonksiyonda yakalanmayan hata nasıl tespit edilir?
Node.js'de 'unhandledRejection' olayını, tarayıcıda 'onunhandledrejection' olayını dinleyerek global olarak yakalanmayan Promise reddetmelerini tespit edebilirsiniz. Bu hatalar genellikle uygulamanın çökmesine yol açar, bu nedenle mutlaka bir hata raporlama sistemi ile entegre edilmelidir.
Birden çok await ifadesinde hata yönetimi nasıl yapılmalı?
Her await için ayrı try-catch yazmak kod tekrarına yol açar. Bunun yerine tüm await'leri tek bir try-catch içine alabilirsiniz. Ancak her bir hatanın ayrı ayrı işlenmesi gerekiyorsa, her await'i kendi bloğuna almak daha doğrudur. Alternatif olarak, Promise.allSettled() ile tüm hataları toplu olarak da işleyebilirsiniz.
Try-catch içinde return kullanmazsam ne olur?
Catch bloğundan sonra kod çalışmaya devam eder. Hata düzeltildiyse sorun yoktur, ancak genellikle hata durumunda fonksiyonun normal akıştan çıkması beklenir. Bu nedenle, hatayı işledikten sonra ya bir değer döndürmeli (return) ya da hatayı tekrar fırlatmalısınız (throw), aksi halde beklenmedik sonuçlarla karşılaşabilirsiniz.
Async/await'te hata yönetiminde en sık yapılan hata nedir?
En sık yapılan hata, hatayı sessizce bastırmak veya catch bloğunda hiçbir işlem yapmamaktır. Bu, hataların fark edilmemesine ve uygulamada gizli sorunlara yol açar. Ayrıca, hataları loglamak ve kullanıcıya anlamlı bir geri bildirim sağlamak önemlidir.






