- Konu sahibi
- #1
async bir fonksiyonun döndürdüğü Promise reddedildiğinde hatayı yakalamanın en doğrudan yolu, ilgili await ifadelerini try...catch bloğuna almaktır. Hata yakalandığında catch içinde mesajı gösterebilir, günlüğe yazabilir veya kullanıcıya uygun bir sonuç döndürebilirsin. İşlemden bağımsız olarak çalışması gereken kod varsa finally bloğunu kullanmalısın.try...catch ile async/await hatası yakalama
await, bir Promise tamamlanana kadar bekler. Promise başarılı olursa değeri alır; reddedilirse hata, normal bir throw işlemi gibi catch bloğuna aktarılır.Aşağıdaki örnekte varsayımsal bir API isteği yapılıyor:
JavaScript:
async function kullaniciyiGetir() {
try {
const yanit = await fetch('/api/kullanici/42');
if (!yanit.ok) {
throw new Error(`Sunucu hatası: ${yanit.status}`);
}
const kullanici = await yanit.json();
console.log(kullanici);
} catch (hata) {
console.error('Kullanıcı alınamadı:', hata.message);
}
}
kullaniciyiGetir();
Burada iki farklı hata türü aynı
catch bloğunda yakalanabilir: fetch() isteğinin ağ nedeniyle reddedilmesi ve isteğin HTTP olarak tamamlanmasına rağmen sunucunun başarısız bir durum kodu döndürmesi. fetch() çoğu HTTP 4xx veya 5xx yanıtında kendiliğinden hata fırlatmadığı için yanit.ok değerini ayrıca kontrol etmek gerekir.İstek başarılı olduğunda kullanıcı verisi
console.log ile yazdırılır. Ağ hatası, geçersiz JSON veya kod içindeki throw new Error(...) işlemi gerçekleşirse catch çalışır. Ancak catch bloğunda yalnızca hatayı gizlemek yerine, uygulamanın ihtiyacına uygun işlem yapmalısın; örneğin kullanıcıya yeniden deneme seçeneği gösterebilir veya güvenli bir varsayılan değer döndürebilirsin.Hata nesnesini güvenli biçimde kullanma
catch içine gelen değer çoğunlukla bir Error nesnesidir ve hata açıklaması hata.message alanında bulunur. Geliştirme sırasında tanılama için hata nesnesinin tamamını günlüğe yazmak daha yararlı olabilir:
JavaScript:
async function veriYukle() {
try {
const yanit = await fetch('/api/veri');
if (!yanit.ok) {
throw new Error(`İstek başarısız oldu: ${yanit.status}`);
}
return await yanit.json();
} catch (hata) {
console.error('Ayrıntılı hata:', hata);
return null;
}
}
Bu örnekte hata yakalandığında fonksiyon
null döndürür. Çağıran kodun bu sonucu kontrol etmesi gerekir; aksi hâlde null üzerinde özellik okumaya çalışmak yeni bir hata oluşturabilir:
JavaScript:
const veri = await veriYukle();
if (veri === null) {
console.log('Veri alınamadı. Kullanıcıya hata mesajı gösterilebilir.');
} else {
console.log(veri);
}
console.error çıktısı hatanın nedenini geliştirme sırasında görmeyi sağlar; tek başına kullanıcıya anlaşılır bir hata ekranı sunmaz. Ayrıca üretim ortamında erişim anahtarı, parola veya kişisel veri gibi hassas bilgileri ayrıntılı hata günlüğüne yazmamalısın.Hatanın çağıran koda aktarılması
Bir fonksiyon hatayı kendi içinde çözemiyorsa
catch içinde throw kullanarak hatayı üst katmana yeniden gönderebilir. Bu yaklaşım, alt seviyede hata kaydı tutup kullanıcıya gösterilecek mesajı daha üst seviyede belirlemek için kullanılır.
JavaScript:
async function siparisGetir() {
try {
const yanit = await fetch('/api/siparis/15');
if (!yanit.ok) {
throw new Error(`Sipariş isteği başarısız: ${yanit.status}`);
}
return await yanit.json();
} catch (hata) {
console.error('Sipariş isteğinde teknik hata:', hata);
throw hata;
}
}
async function ekraniHazirla() {
try {
const siparis = await siparisGetir();
console.log(siparis);
} catch (hata) {
console.log('Sipariş şu anda gösterilemiyor. Lütfen daha sonra tekrar deneyin.');
}
}
-ekraniHazirla();
Kodda
-ekraniHazirla() ifadesi kullanılmaz; doğru çağrı aşağıdaki gibi olmalıdır:
JavaScript:
ekraniHazirla();
İlk
catch teknik ayrıntıyı kaydeder ve hatayı kaybetmeden yeniden fırlatır. İkinci catch ise kullanıcıya teknik olmayan bir mesaj gösterir. Hatayı yeniden fırlatmazsan üst katman işlemin başarısız olduğunu öğrenemez.try, catch ve finally ne zaman çalışır?
Aşağıdaki ayrım, hangi bloğa ne koyacağını belirlemene yardımcı olur.
| Blok | Ne zaman çalışır? | Uygun kullanım |
|---|---|---|
| try | Normal akışta işlem denenirken | await edilen istek veya hata üretebilecek kod |
| catch | try içinde hata oluştuğunda | Hata kaydı, kullanıcı mesajı veya alternatif sonuç |
| finally | İşlem başarılı olsa da başarısız olsa da | Yükleniyor göstergesini kapatma veya geçici kaynağı temizleme |
finally kullanabilirsin:
JavaScript:
async function verileriYukle() {
yukleniyorGoster();
try {
const yanit = await fetch('/api/veriler');
if (!yanit.ok) {
throw new Error(`HTTP durum kodu: ${yanit.status}`);
}
return await yanit.json();
} catch (hata) {
console.error(hata);
return null;
} finally {
yukleniyorGizle();
}
}
finally içindeki kod, try başarılı olsa da catch çalışsa da yürütülür. Bu nedenle burada sonucu değiştirecek bir return kullanmak dikkat gerektirir; finally içindeki return, önceki dönüş değerini veya hatayı geçersiz kılabilir.await edilen fonksiyonun dışındaki hatalar
Bir
async fonksiyonu çağırdığında dönen Promise reddedilebilir. Çağrı doğrudan await edilmiyorsa, dışarıda ayrıca hata yakalamalısın:
JavaScript:
async function baslat() {
try {
await verileriYukle();
} catch (hata) {
console.error('Başlatma işlemi başarısız:', hata);
}
}
baslat();
baslat() çağrısını hiçbir yerde await etmez veya .catch(...) ile izlemezsen, üst seviyede oluşan hata ele alınmamış bir Promise reddedilmesine dönüşebilir. Alternatif olarak şu kullanım da geçerlidir:
JavaScript:
baslat().catch((hata) => {
console.error('Beklenmeyen hata:', hata);
});
Birden fazla bağımsız işlemi
Promise.all() ile çalıştırıyorsan, bunları da try...catch içine alabilirsin. Promise’lerden biri reddedildiğinde Promise.all() reddedilir ve catch çalışır; bu, diğer işlemlerin kesin olarak durduğu anlamına gelmez.Sık sorulan sorular
try...catch, HTTP 404 veya 500 hatasını kendiliğinden yakalar mı?
fetch() isteğin sunucuya ulaşıp 404 veya 500 yanıtı alırsa Promise genellikle reddedilmez. Bu nedenle yanit.ok değerini kontrol edip gerekiyorsa kendin throw new Error(...) kullanmalısın. Ağ bağlantısı kurulamazsa veya istek teknik nedenle tamamlanamazsa fetch() reddedilir ve hata doğrudan catch bloğuna ulaşır.catch bloğu boş bırakılabilir mi?
Bırakılabilir ancak genellikle doğru değildir. Hatanın sessizce yok sayılması, sorunun nedenini bulmayı zorlaştırır ve kullanıcıya işlemin başarısız olduğunu bildirmeyebilir. Hatanın tamamını kullanıcıya göstermek yerine teknik ayrıntıyı günlüğe yazıp kullanıcıya güvenli ve anlaşılır bir mesaj vermek daha uygundur.