JAVASCRIPT ASYNC AWAIT PROMISE YÖNETMEK

Vimaj8 dk okuma
Sarı JS kare logosu yanında iki yatay akış senkron düz çizgi ve asenkron kavisli kesik çizgi Promise üç durum dairesi pending fulfilled rejected

JavaScript'in asenkron yapısı modern web'in temelidir. Bir butona tıklandığında sunucudan veri çekilir; sayfa donmaz, kullanıcı diğer işlere devam edebilir. Bu davranışın altında Promise vardır. async/await ise Promise'leri yazmayı senkron koda benzer şekilde okunaklı yapar.

1. Promise nedir?

Henüz tamamlanmamış bir asenkron işlemin sonucunu temsil eden nesne. Davranışın ince ayrıntıları için web teknolojileri dokümantasyonu ayrıntılı bir başvuru kaynağı sağlar. Üç durumdan biri:

  • Pending: İşlem devam ediyor
  • Fulfilled: İşlem başarıyla tamamlandı
  • Rejected: İşlem hata ile sonuçlandı

Temel Promise yapısı

const veri = new Promise((resolve, reject) => {
  setTimeout(() => {
    const sonuc = Math.random();
    if (sonuc > 0.5) {
      resolve(sonuc);
    } else {
      reject(new Error('Yetersiz değer'));
    }
  }, 1000);
});

veri
  .then(deger => console.log('Başarılı:', deger))
  .catch(hata => console.error('Hata:', hata));

2. async/await syntax

Aynı kodu daha okunabilir yazmak için:

async function veriCek() {
  try {
    const sonuc = await veri;
    console.log('Başarılı:', sonuc);
  } catch (hata) {
    console.error('Hata:', hata);
  }
}

veriCek();

İki kural:

  • async: Bir fonksiyonu Promise döndüren fonksiyona çevirir
  • await: Promise'in tamamlanmasını bekler; sadece async fonksiyon içinde kullanılır

3. fetch ile gerçek örnek

// Promise zinciri ile
fetch('/api/urunler')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));

// async/await ile (daha okunabilir)
async function urunleriGetir() {
  try {
    const response = await fetch('/api/urunler');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}

İkisi de aynı işi yapıyor; async/await daha senkron-benzeri okunuyor.

4. Hata yönetimi

try/catch ile

async function islem() {
  try {
    const sonuc = await riskliIslem();
    return sonuc;
  } catch (error) {
    if (error.code === 'NETWORK_ERROR') {
      console.log('İnternet bağlantısı yok');
    } else {
      console.error('Bilinmeyen hata:', error);
    }
    throw error; // gerekirse yukarı fırlat
  }
}

.catch() ile

islem()
  .then(sonuc => console.log(sonuc))
  .catch(error => console.error(error))
  .finally(() => console.log('Bitti'));

finally hata olsun olmasın her zaman çalışır; loading state kapatma gibi temizlik işleri için.

5. Paralel çalıştırma: Promise.all

Birden fazla bağımsız Promise'i paralel çalıştırmak için.

// Yanlış: sırayla bekler (yavaş)
async function yavasYol() {
  const kullanici = await fetch('/api/user');
  const siparisler = await fetch('/api/orders');
  const yorumlar = await fetch('/api/reviews');
  // Toplam 3 saniye (her biri 1sn)
}

// Doğru: paralel (hızlı)
async function hizliYol() {
  const [kullanici, siparisler, yorumlar] = await Promise.all([
    fetch('/api/user'),
    fetch('/api/orders'),
    fetch('/api/reviews')
  ]);
  // Toplam 1 saniye (en yavaşı kadar)
}

Promise.all biri başarısız olursa tümü başarısız sayılır. Bunu engellemek için Promise.allSettled kullanılır.

6. Promise.allSettled, Promise.race, Promise.any

MethodDavranış
Promise.allTümünü bekler; biri hata verirse hep hata
Promise.allSettledTümünü bekler; her birinin status ve value/reason'ı döner
Promise.raceİlk tamamlananı döner (başarı veya hata)
Promise.anyİlk BAŞARILIYI döner; tümü hata verirse hata
VS Code dark tema editörde async fonksiyon içinde await fetch ve try catch hata yakalama bloklarının syntax highlighted JavaScript kodu

7. Klasik Hatalar hatalar

1. await unutmak

// Yanlış
async function getir() {
  const data = fetch('/api'); // await unutuldu
  return data.json(); // hata: data Promise nesnesi
}

// Doğru
async function getir() {
  const data = await fetch('/api');
  return data.json();
}

2. forEach içinde await

// Yanlış: forEach await beklemez
[1, 2, 3].forEach(async (id) => {
  await islem(id);
});
console.log('bitti'); // önce yazılır

// Doğru: for...of veya Promise.all
for (const id of [1, 2, 3]) {
  await islem(id);
}
// veya paralel
await Promise.all([1, 2, 3].map(islem));

3. Try/catch içinde await olmadan

// Yanlış: hata yakalanmaz
async function islem() {
  try {
    return riskliPromise(); // await yok
  } catch (e) {
    // bu blok çalışmaz; Promise hatası dışarı çıkar
  }
}

// Doğru
async function islem() {
  try {
    return await riskliPromise();
  } catch (e) {
    console.error(e);
  }
}

4. Çoklu reject yakalama

// Yanlış: tek catch yetersiz
Promise.all([istek1, istek2, istek3])
  .catch(e => console.error(e));
// İlk reject yakalanır; diğer hatalar görünmez

// Doğru: allSettled
const sonuclar = await Promise.allSettled([istek1, istek2, istek3]);
sonuclar.forEach(sonuc => {
  if (sonuc.status === 'rejected') {
    console.error(sonuc.reason);
  }
});

8. Async iteration

Asenkron veriler üzerinde for...of benzeri döngü:

async function* sayilar() {
  yield 1;
  yield 2;
  yield 3;
}

for await (const num of sayilar()) {
  console.log(num);
}

Stream'ler için tipik kullanım; satır satır gelen veriyi sırayla işleme.

9. Timeout ve cancel

JavaScript Promise'leri yerleşik cancel etmez. Modern çözüm AbortController:

const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);

try {
  const response = await fetch('/api', {
    signal: controller.signal
  });
  clearTimeout(timeoutId);
  return await response.json();
} catch (error) {
  if (error.name === 'AbortError') {
    console.log('İstek 5 saniyede bitmediği için iptal');
  }
}

10. Performance ipuçları

  • Bağımsız işleri paralel yap. Promise.all ile zaman tasarrufu
  • Promise'leri yeniden kullan. Aynı verinin tekrar çekilmesi yerine cache
  • Stream kullan. Büyük veri için tek seferde değil parça parça
  • AbortController ile iptal et. Gereksiz istek devam etmesin
  • Microtask spam'ından kaçın. Sonsuz Promise zinciri main thread'i tüketir
Paralel ve seri Promise çalıştırma zaman çizgisi karşılaştırması üstte üç ardışık await coral mavi amber bloğu altta Promise all ile aynı anda yan yana üç blok

11. Sonraki Adım Setleri

Async/await ve Promise modern JavaScript'in temel becerilerinden. Konuyu profesyonel düzeyde işlemek için kapsamlı JavaScript eğitimi programları asenkron programlama konularını derinlemesine işler.

12. Kritik Detaylar

JavaScript async/await syntax'ı Promise'lerin görsel kabuğu; altta hâlâ Promise mantığı var. try/catch ile hata yönetimi, Promise.all ile paralel çalıştırma, AbortController ile iptal modern asenkron kodun temel araçları. await unutmak, forEach içinde await kullanmak, Promise.all yerine sıralı await yazmak yaygın hatalar. Doğru kullanım hem performans hem okunabilirlik için kritik.

Sıkça Sorulan Sorular

async/await mı Promise zinciri mi daha iyi?

İkisi de aynı işi yapar; tercih okunabilirliğe göre. async/await senkron-benzeri okunur; lineer mantık için daha temiz. Promise zinciri (.then.then.catch) fonksiyonel programlama yapısı için daha uygun, transform işlemlerinde okunabilir. Çoğu modern proje async/await tercih eder; ama her ikisi de aynı projede karışık kullanılabilir.

await neden sadece async fonksiyon içinde kullanılabilir?

JavaScript spec gereği. async kelimesi fonksiyona 'asenkron çalış' işaret veriyor; await ise 'burada Promise'i çöz' diyor. async olmadan await'in çalışma bağlamı tanımsız olur. Modüllerin en üst seviyesinde 'top-level await' kullanılabilir (ES2022); ama fonksiyon içinde mutlaka async gerek.

Promise.all biri hata verirse ne olur?

Tüm Promise.all hata verir; başarılı Promise'ler dahil hiçbir sonuç dönmez. Bunu engellemek için Promise.allSettled kullanılır; her Promise'in durumu (fulfilled/rejected) ve değeri ayrı ayrı döner. Bireysel hataları yönetebilmek için allSettled, hep birlikte başarı isteniyorsa all kullanılır.

forEach içinde await neden çalışmıyor?

forEach metodu async callback'i bekler ama callback'ler içindeki await'leri beklemez; tüm callback'leri tetikler ve devam eder. Sıralı işlem için for...of veya for döngüsü kullanılır; bunlar her iterasyonda await ile durur. Paralel işlem için Promise.all ile map kombinasyonu uygundur.

AbortController ne zaman gerekli?

Üç senaryoda. Birincisi: kullanıcı sayfayı değiştirir, devam eden fetch artık gereksiz. İkincisi: timeout; istek belirli süreden uzun sürerse iptal. Üçüncüsü: race condition; eski istek yerine yeni istek başlatma. React projelerinde useEffect cleanup içinde AbortController kullanmak yaygın pratiktir.

Promise yerleşik cancel olmazsa ne yapılır?

Promise tek başına iptal edilmez ama akış kontrolüyle yönetilebilir. AbortController fetch API ile entegre çalışır. Custom Promise'ler için bir flag kullanılır: Promise içinde periyodik 'iptal mi edildi' kontrolü. Bazı kütüphaneler (Bluebird) cancelable Promise sunar; native JavaScript'te yok.

Async fonksiyon ne döndürür?

Her zaman Promise. Eğer return ile değer dönerseniz Promise.resolve(deger) gibi sarılır. return ile throw ederseniz Promise.reject(error). Bu nedenle async fonksiyonu çağırdığınızda await ile beklemek veya .then ile zincirlemek gerekir; senkron değer döndüremez.

 Vimaj