JavaScript Dilinde Asenkron Programlama: Kapsamlı Bir Kılavuz
JavaScript, doğası gereği tek iş parçacıklı (single-threaded) bir dildir. Bu durum, uzun süren veya dış kaynaklara bağımlı işlemleri (örneğin, ağ istekleri, dosya okuma/yazma) doğrudan ana iş parçacığında yürütmenin kullanıcı arayüzünü kilitlemesine ve uygulamanın donmasına neden olacağı anlamına gelir. Bu tür senaryolarda uygulamanın yanıt verebilirliğini korumak ve verimli çalışmasını sağlamak için asenkron programlama teknikleri kullanılır. Bu kılavuz, JavaScript'te asenkron işlemlerin nasıl yönetildiğini, özellikle modern async/await sözdizimi ve altında yatan Promise mekanizmasını adım adım açıklamaktadır.
Sözdizimi
Modern JavaScript'te asenkron kod yazmanın en yaygın ve okunabilir yolu async ve await anahtar kelimelerini kullanmaktır. Bu sözdizimi, Promise tabanlı asenkron kodun senkron koda benzer bir şekilde yazılmasını sağlar.
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Veri çekme hatası:', error);
  }
}
fetchData();
Detaylı Açıklama
- 
    
asyncAnahtar Kelimesi: Bir fonksiyonun önüneasyncanahtar kelimesini eklemek, o fonksiyonu her zaman birPromisedöndüren asenkron bir fonksiyon yapar. Eğer fonksiyon açıkça birPromisedöndürmüyorsa, JavaScript otomatik olarak döndürülen değeri birPromiseiçine sarar. Bu, asenkron fonksiyonların zincirleme (chaining) bir şekilde veyaawaitile kullanılabilmesini sağlar. - 
    
awaitAnahtar Kelimesi: Sadeceasyncolarak işaretlenmiş bir fonksiyonun içinde kullanılabilenawaitanahtar kelimesi, birPromise'in çözülmesini (yani başarılı bir şekilde tamamlanmasını veya reddedilmesini) bekler.awaitkullanılan satırda kodun yürütülmesi duraklatılır vePromiseçözüldüğünde devam eder. EğerPromisebaşarılı olursa,awaitifadesiPromise'in değerini döndürür. EğerPromisereddedilirse,awaitbir hata fırlatır ve bu hatatry...catchbloğu ile yakalanabilir. - 
    
PromiseNesnesi:async/awaitsözdiziminin temelindePromisenesnesi yatar. BirPromise, asenkron bir işlemin nihai sonucunu (başarı değeri veya hata nedeni) temsil eden bir JavaScript nesnesidir. Üç ana durumu vardır:pending(beklemede): Asenkron işlem henüz tamamlanmadı.fulfilled(tamamlandı/çözüldü): Asenkron işlem başarıyla tamamlandı ve bir değer döndürdü.rejected(reddedildi): Asenkron işlem bir hata nedeniyle başarısız oldu.
Promise'ler,.then()metodu ile başarılı sonuçları,.catch()metodu ile hataları ve.finally()metodu ile her iki durumda da çalışacak kod bloklarını yönetmek için kullanılır. 
Pratik Kullanım Örnekleri
Örnek 1: Temel Asenkron İşlem ve Veri Çekme
Bu örnek, bir ağ isteğini simüle eden bir fonksiyonun async/await ile nasıl çağrıldığını ve sonucunun nasıl işlendiğini göstermektedir.
function simulateNetworkRequest(url) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(`Veri ${url} adresinden başarıyla çekildi.`);
      resolve({ id: 1, data: `Veri ${url} için` });
    }, 2000); // 2 saniye gecikme
  });
}
async function getDataFromApi() {
  console.log('API\'den veri çekiliyor...');
  const result = await simulateNetworkRequest('https://api.example.com/users');
  console.log('Çekilen veri:', result);
  console.log('Veri çekme işlemi tamamlandı.');
}
getDataFromApi();
// Beklenen Çıktı:
// API'den veri çekiliyor...
// (2 saniye sonra)
// Veri https://api.example.com/users adresinden başarıyla çekildi.
// Çekilen veri: { id: 1, data: 'Veri https://api.example.com/users için' }
// Veri çekme işlemi tamamlandı.
Örnek 2: Hata Yönetimi
Asenkron işlemlerde hata yönetimi kritik öneme sahiptir. try...catch blokları, await ile tetiklenen Promise reddedilmelerini yakalamak için kullanılır.
function simulateFailedNetworkRequest(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (Math.random() > 0.5) { // Rastgele hata simülasyonu
        reject(new Error(`Hata: ${url} adresinden veri çekilemedi.`));
      } else {
        resolve({ id: 2, data: `Başarılı veri ${url} için` });
      }
    }, 1500);
  });
}
async function fetchDataWithErrorHandling() {
  console.log('Hata yönetimi ile veri çekiliyor...');
  try {
    const data = await simulateFailedNetworkRequest('https://api.example.com/products');
    console.log('Çekilen veri:', data);
  } catch (error) {
    console.error('Bir hata oluştu:', error.message);
  } finally {
    console.log('Veri çekme girişimi sonlandı.');
  }
}
fetchDataWithErrorHandling();
// Beklenen Çıktı (başarılı olursa):
// Hata yönetimi ile veri çekiliyor...
// (1.5 saniye sonra)
// Çekilen veri: { id: 2, data: 'Başarılı veri https://api.example.com/products için' }
// Veri çekme girişimi sonlandı.
// Beklenen Çıktı (hata olursa):
// Hata yönetimi ile veri çekiliyor...
// (1.5 saniye sonra)
// Bir hata oluştu: Hata: https://api.example.com/products adresinden veri çekilemedi.
// Veri çekme girişimi sonlandı.
Örnek 3: Paralel Asenkron İşlemler
Birden fazla asenkron işlemi aynı anda başlatmak ve hepsinin tamamlanmasını beklemek için Promise.all() kullanılabilir. Bu, bekleme sürelerini optimize eder.
function fetchResource(resourceName, delay) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(`${resourceName} çekildi.`);
      resolve(`${resourceName} verisi`);
    }, delay);
  });
}
async function fetchMultipleResources() {
  console.log('Kaynaklar paralel olarak çekiliyor...');
  const [users, products, orders] = await Promise.all([
    fetchResource('Kullanıcılar', 3000), // 3 saniye
    fetchResource('Ürünler', 1000),    // 1 saniye
    fetchResource('Siparişler', 2000)   // 2 saniye
  ]);
  console.log('Tüm kaynaklar çekildi.');
  console.log('Kullanıcılar:', users);
  console.log('Ürünler:', products);
  console.log('Siparişler:', orders);
}
fetchMultipleResources();
// Beklenen Çıktı:
// Kaynaklar paralel olarak çekiliyor...
// (1 saniye sonra) Ürünler çekildi.
// (2 saniye sonra) Siparişler çekildi.
// (3 saniye sonra) Kullanıcılar çekildi.
// Tüm kaynaklar çekildi.
// Kullanıcılar: Kullanıcılar verisi
// Ürünler: Ürünler verisi
// Siparişler: Siparişler verisi
Önemli Notlar
- 
    
awaitKullanımı:awaitanahtar kelimesi yalnızcaasyncolarak işaretlenmiş fonksiyonların içinde kullanılabilir. Global kapsamda veya senkron fonksiyonlarda doğrudanawaitkullanmaya çalışmak sözdizimi hatasına yol açacaktır. - 
    
asyncFonksiyonların Dönüş Değeri: Herasyncfonksiyon, döndürdüğü değeri otomatik olarak birPromiseiçine sarar. Eğer bir değer döndürülmezse,Promise.resolve(undefined)döndürülür. - 
    
Hata Yönetimi:
async/awaitile hata yönetimi içintry...catchblokları kullanmak, senkron koddaki hata yönetimine benzer bir yapı sunarak kodu daha okunabilir hale getirir.Promisereddedildiğinde,awaitbir hata fırlatır ve bucatchbloğu tarafından yakalanır. - 
    
Promise.all()ve Paralellik: Birden fazla bağımsız asenkron işlemi paralel olarak yürütmek ve hepsinin sonucunu beklemek içinPromise.all()kullanın. Bu, toplam yürütme süresini önemli ölçüde azaltabilir. Eğer işlemlerden herhangi biri reddedilirse,Promise.all()hemen reddedilerek hatayı döndürür. - 
    
Bloke Edici Olmayan (Non-blocking) Yapı: Asenkron işlemler, uzun süren görevlerin ana iş parçacığını bloke etmesini engeller. Bu sayede uygulamanız kullanıcı etkileşimlerine yanıt vermeye devam eder ve daha akıcı bir kullanıcı deneyimi sunar.
 - 
    
Callback Hell'den Kaçınma:async/await, iç içe geçmiş yoğun geri çağırma (callback) fonksiyonlarından kaynaklanan "callback hell" sorununu çözmek için modern ve daha temiz bir alternatif sunar. Bu, kodun okunabilirliğini ve bakımını büyük ölçüde iyileştirir. 
        
                
            
            
Yorum yap
Yorumlar