Asenkron programlama, JavaScript’in güçlü özelliklerinden biridir. Günümüzün dinamik web uygulamalarında, asenkron işlemler kaçınılmaz hale gelmiştir. Ancak her şey gibi, asenkron işlemler de doğru yönetilmediğinde karmaşık ve hata yapmaya yatkın hale gelir. Neyse ki JavaScript’in `async/await` yapısı, asenkron programlamayı daha okunabilir ve yönetilebilir kılmak için tasarlanmıştır. Ancak bir konu var ki, onu atlamak kolaydır: hata yönetimi. Gelin, bu konuyu derinlemesine inceleyelim ve asenkron kod yazarken karşılaşabileceğiniz hata yönetimi zorluklarını nasıl aşacağınızı öğrenelim.
Async/Await Nedir ve Ne Zaman Kullanılır?
```javascript
async function getData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
}
```
Buradaki örnekte, `getData()` fonksiyonu, `fetch()` çağrısının sonucunu bekler ve veriyi işleme alır. Her şey sırayla, okunabilir bir şekilde gerçekleşir.
Hata Yönetimi: Try/Catch ve Async/Await
Bir `async` fonksiyonu içinde herhangi bir hata meydana gelirse, bu hata bir `Promise` olarak yakalanır ve biz bu hatayı `catch` bloğunda ele alabiliriz. İşte basit bir örnek:
```javascript
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('Veri alınamadı!');
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Hata:', error.message);
}
}
```
Bu örnekte, `try` bloğunda `fetch` işlemi yapılır ve eğer `response.ok` durumu false dönerse, hata fırlatılır. Bu hata, `catch` bloğunda yakalanır ve ekrana yazdırılır.
Promise.all ve Async/Await Birlikteliği
```javascript
async function fetchMultipleData() {
try {
const [users, posts] = await Promise.all([
fetch('https://api.example.com/users').then(res => res.json()),
fetch('https://api.example.com/posts').then(res => res.json())
]);
console.log('Kullanıcılar:', users);
console.log('Gönderiler:', posts);
} catch (error) {
console.error('Hata:', error.message);
}
}
```
Bu örnekte, iki farklı API çağrısı paralel olarak yapılır ve her iki işlem de tamamlandığında sonuçlar konsola yazdırılır. `Promise.all` ile yapılan paralel işlemler, daha verimli ve hızlı çalışmanızı sağlar.
Performans İyileştirmeleri
Örneğin, gereksiz yere çok fazla `await` kullanmaktan kaçınmak ve mümkün olduğunda paralel işlemler yapmak, uygulamanızın hızını artırabilir. Ayrıca, veri alma işlemleri sırasında yalnızca gereken verilerin çekilmesi de performans üzerinde büyük bir fark yaratır.
```javascript
async function fetchDataOptimized() {
try {
const userDataPromise = fetch('https://api.example.com/users').then(res => res.json());
const postDataPromise = fetch('https://api.example.com/posts').then(res => res.json());
const [userData, postData] = await Promise.all([userDataPromise, postDataPromise]);
console.log('Kullanıcı Verisi:', userData);
console.log('Gönderi Verisi:', postData);
} catch (error) {
console.error('Hata:', error.message);
}
}
```
Bu örnekte, veri alma işlemleri paralel yapılır ve her iki işlem de birbirini beklemeden tamamlanır. Bu, işlemlerin toplam süresini önemli ölçüde azaltır.
Gerçek Hayat Senaryoları: Web Uygulamalarında Hata Yönetimi
Bir e-ticaret sitesinde, ürünlerin fiyat bilgisini ve stok durumunu paralel olarak alabiliriz. Ancak her iki API’den de hata alabiliriz. Hata yönetimini doğru bir şekilde yaparak kullanıcı deneyimini iyileştirebiliriz.
```javascript
async function loadProductDetails() {
try {
const [productInfo, stockInfo] = await Promise.all([
fetch('https://api.example.com/product').then(res => res.json()),
fetch('https://api.example.com/stock').then(res => res.json())
]);
console.log('Ürün Bilgisi:', productInfo);
console.log('Stok Durumu:', stockInfo);
} catch (error) {
console.error('Ürün yüklenirken hata oluştu:', error.message);
}
}
```