Neler yeni

Yazılım Forum

Tüm özelliklerimize erişmek için şimdi bize katılın. Kayıt olduktan ve giriş yaptıktan sonra konu oluşturabilecek, mevcut konulara yanıt gönderebilecek, itibar kazanabilecek, özel mesajlaşmaya erişebilecek ve çok daha fazlasını yapabileceksiniz! Bu hizmetlerimiz ise tamamen ücretsiz ve kurallara uyulduğu sürece sınırsızdır, o zaman ne bekliyorsunuz? Hadi, sizde aramıza katılın!

JavaScript'te Promise API Kullanımı: Asenkron Programlamada Ustalık

Modern web uygulamaları, kullanıcı deneyimini kesintiye uğratmadan arka planda veri çekme, dosya işleme ve diğer zaman alıcı operasyonları gerçekleştirmek zorundadır. Bu tür asenkron işlemleri yönetmek, JavaScript'in en önemli konularından biridir. Geleneksel olarak, asenkron işlemler callback (geri arama) fonksiyonları ile yönetilirdi. Ancak, iç içe geçmiş callback'ler (callback hell veya pyramid of doom olarak bilinir), kodun okunabilirliğini ve bakımını zorlaştırıyordu. İşte tam da bu noktada Promise API devreye girer ve asenkron programlamaya çok daha zarif ve yönetilebilir bir yaklaşım sunar.

Promise Nedir?

Bir Promise (Söz), asenkron bir işlemin nihai sonucunu (başarılı tamamlanması veya başarısız olması) temsil eden bir JavaScript nesnesidir. Bir Promise, üç ana durumdan birinde olabilir:

  • Pending (Beklemede): Başlangıç durumu, ne başarıyla tamamlanmış ne de reddedilmiş.
  • Fulfilled (Yerine Getirilmiş): İşlem başarıyla tamamlandı ve bir değer döndürdü.
  • Rejected (Reddedildi): İşlem başarısız oldu ve bir hata döndürdü.

Bir Promise, 'pending' durumundan 'fulfilled' veya 'rejected' durumuna geçer ve bir kez geçtikten sonra durumu bir daha değişmez. Bu özelliği, asenkron operasyonların öngörülebilirliğini artırır.

Temel Promise Oluşturma ve Kullanımı

Yeni bir Promise oluşturmak için `new Promise()` yapıcısını kullanırız. Bu yapıcı, iki argüman alan bir yürütme fonksiyonu alır: `resolve` ve `reject`.

Kod:
const myFirstPromise = new Promise((resolve, reject) => {
  // Asenkron bir işlem başlat
  setTimeout(() => {
    const success = true; // Gerçek bir senaryoda bu bir API yanıtı veya dosya okuma sonucu olabilir
    if (success) {
      resolve('Veri başarıyla alındı!'); // Promise'i başarılı olarak işaretle
    } else {
      reject('Veri alma işleminde hata oluştu.'); // Promise'i reddedilmiş olarak işaretle
    }
  }, 2000); // 2 saniye sonra işlemi tamamla
});

myFirstPromise
  .then((message) => {
    console.log('[b]Başarılı:[/b]', message);
  })
  .catch((error) => {
    console.error('[b]Hata:[/b]', error);
  })
  .finally(() => {
    console.log('[b]İşlem tamamlandı.[/b]');
  });

// Çıktı (2 saniye sonra başarılı olursa):
// Başarılı: Veri başarıyla alındı!
// İşlem tamamlandı.

Bu örnekte, `setTimeout` ile simüle edilen bir asenkron işlemimiz var. İşlem başarılı olursa `resolve()`, hata olursa `reject()` çağrılır.

`Promise.resolve()` ve `Promise.reject()`

Bazen hemen çözülen veya hemen reddedilen bir Promise'e ihtiyacımız olabilir. Bu durumda `Promise.resolve()` ve `Promise.reject()` statik metotları kullanılır.

Kod:
// Hemen çözülen bir Promise
Promise.resolve('Bu Promise hemen çözüldü.')
  .then(value => console.log(value)); // Çıktı: Bu Promise hemen çözüldü.

// Hemen reddedilen bir Promise
Promise.reject(new Error('Bu Promise hemen reddedildi.'))
  .catch(error => console.error(error.message)); // Çıktı: Bu Promise hemen reddedildi.

Promise Zincirleme (.then(), .catch(), .finally())

Promise'lerin en güçlü özelliklerinden biri, art arda sıralanabilmeleridir. Her `.then()` çağrısı yeni bir Promise döndürür, bu da zincirleme yapmaya olanak tanır. Bu sayede, bir işlemin sonucuna bağlı olarak başka bir işlem başlatabiliriz.

.then() Metodu: Promise başarıyla tamamlandığında çalışacak kodu tanımlar. Bir veya iki fonksiyon alabilir: `onFulfilled` ve `onRejected`. Genellikle sadece `onFulfilled` kullanılır ve hatalar için `.catch()` tercih edilir.

Kod:
function fetchData(url) {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(`[i]${url} adresinden veri çekiliyor...[/i]`);
      resolve(`Veri çekildi: ${url}`);
    }, 1500);
  });
}

fetchData('https://api.example.com/users')
  .then(userData => {
    console.log(userData);
    // İlk Promise'in sonucuna bağlı olarak yeni bir Promise döndürüyoruz
    return fetchData('https://api.example.com/posts');
  })
  .then(postData => {
    console.log(postData);
    console.log('[b]Tüm veriler başarıyla alındı.[/b]');
  })
  .catch(error => {
    console.error('[u]Zincirleme sırasında bir hata oluştu:[/u]', error);
  });

.catch() Metodu: Promise zincirindeki herhangi bir noktada meydana gelen hataları yakalamak için kullanılır. En iyi uygulama, zincirin sonuna bir `.catch()` bloğu eklemektir. Bu, zincirdeki tüm Promise'lerden fırlatılan hataları tek bir noktada ele almanızı sağlar.

Kod:
function riskyOperation() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const errorOccurred = true; // Hata olduğunu simüle et
      if (errorOccurred) {
        reject(new Error('Riskli işlem başarısız oldu!'));
      } else {
        resolve('Riskli işlem başarılı oldu.');
      }
    }, 1000);
  });
}

riskyOperation()
  .then(result => {
    console.log(result);
    return 'İşlem devam ediyor...';
  })
  .then(nextStep => {
    console.log(nextStep);
    // Burada bir hata daha fırlatabiliriz
    // throw new Error('Zincirde beklenmedik hata!');
  })
  .catch(err => {
    console.error('[b]GENEL HATA YAKALANDI:[/b]', err.message);
  })
  .finally(() => {
    console.log('Riskli işlem bloğu tamamlandı, hata olsa da olmasa da çalışırım.');
  });

.finally() Metodu: Promise'in durumu ne olursa olsun (başarılı veya reddedilmiş) çalıştırılacak kodu tanımlar. Kaynakları serbest bırakma, yükleme göstergelerini kapatma gibi temizlik işlemleri için idealdir.

Gelişmiş Promise Metotları

Birden fazla Promise'i aynı anda yönetmek için Promise API, bir dizi statik metot sunar:

Promise.all(iterable): Bir dizi Promise'i alır ve tüm Promise'ler başarılı olduğunda çözülen tek bir Promise döndürür. Eğer herhangi bir Promise reddedilirse, `Promise.all` hemen reddedilir ve ilk reddedilen Promise'in hatasını döndürür.

Kod:
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3])
  .then((values) => {
    console.log('[b]Promise.all Başarılı:[/b]', values); // [3, 42, 'foo']
  })
  .catch((error) => {
    console.error('[b]Promise.all Hata:[/b]', error);
  });

// Eğer promise2 yerine Promise.reject(new Error('Hata')) olsaydı,
// Promise.all hemen reddedilirdi.

Promise.race(iterable): Bir dizi Promise alır ve bu Promise'lerden ilk tamamlanan (çözülen veya reddedilen) ile aynı değeri/hatayı döndürür. Yarışan Promise'lerden hangisi önce biterse, onun sonucunu döndürür.

Kod:
const promiseRace1 = new Promise((resolve) => setTimeout(resolve, 500, 'Birincil sunucu hazır.'));
const promiseRace2 = new Promise((resolve) => setTimeout(resolve, 100, 'Yedek sunucu daha hızlı.'));

Promise.race([promiseRace1, promiseRace2])
  .then((value) => {
    console.log('[b]Promise.race Kazanan:[/b]', value); // Çıktı: Yedek sunucu daha hızlı.
  });

Promise.allSettled(iterable): (ES2020) Bir dizi Promise alır ve tüm Promise'ler çözüldüğünde (başarılı veya reddedilmiş olsalar bile) çözülen tek bir Promise döndürür. Sonuç, her Promise'in durumunu (status: 'fulfilled' veya 'rejected') ve değerini (value) veya hatasını (reason) içeren bir nesneler dizisidir.

Kod:
const promiseAS1 = Promise.resolve('Başarılı Veri');
const promiseAS2 = Promise.reject(new Error('Veri çekilemedi'));

Promise.allSettled([promiseAS1, promiseAS2])
  .then((results) => {
    console.log('[b]Promise.allSettled Sonuçları:[/b]', results);
    /*
    Çıktı:
    [
      { status: 'fulfilled', value: 'Başarılı Veri' },
      { status: 'rejected', reason: Error: Veri çekilemedi }
    ]
    */
  });

Promise.any(iterable): (ES2021) Bir dizi Promise alır ve Promise'lerden herhangi biri başarılı olduğunda çözülen tek bir Promise döndürür. Eğer tüm Promise'ler reddedilirse, bir `AggregateError` ile reddedilir.

Kod:
const promiseAny1 = new Promise((resolve, reject) => setTimeout(reject, 200, 'Sunucu 1 hatası.'));
const promiseAny2 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'Sunucu 2 başarılı.'));
const promiseAny3 = new Promise((resolve, reject) => setTimeout(resolve, 300, 'Sunucu 3 başarılı.'));

Promise.any([promiseAny1, promiseAny2, promiseAny3])
  .then((value) => {
    console.log('[b]Promise.any Kazanan:[/b]', value); // Çıktı: Sunucu 2 başarılı.
  })
  .catch((error) => {
    console.error('[b]Promise.any Hata:[/b]', error);
  });

// Eğer tüm Promise'ler reddedilirse, AggregateError fırlatılır.
// Promise.any([Promise.reject('a'), Promise.reject('b')]).catch(err => console.log(err.errors));

Hata Yönetimi ve En İyi Pratikler

"Asenkron programlamanın kalbinde, başarısızlıkları öngörmek ve bunlara uygun şekilde tepki vermektir." - Anonim

* Her Zaman Bir `.catch()` Ekleyin: Promise zincirinizin sonuna bir `.catch()` bloğu eklemek, beklenmeyen hataların uygulamanızı çökertmesini engeller ve hata ayıklamayı kolaylaştırır.
* Gereksiz İç İçe Promise'lerden Kaçının: Callback cehennemine benzer şekilde Promise cehennemine düşmemek için `.then()` zincirleme özelliğini etkin kullanın. Her `.then()` bloğundan yeni bir Promise döndürerek kodu düz tutun.
* Senkron Kodları Promise İçine Koymayın: Promise'ler asenkron işlemler içindir. Senkron kodları Promise yapısı içine koymak performansa fayda sağlamaz, aksine okunurluğu azaltır.
* Hataları Yeniden Fırlatın (Re-throw Errors): Bazen bir `.catch()` bloğunda hatayı işledikten sonra, hatanın zincirde yukarı doğru yayılmaya devam etmesini isteyebilirsiniz. Bu durumda, hatayı yeniden fırlatabilirsiniz (`throw error;`).

Async/Await ile Promise Kullanımı

ES2017 ile tanıtılan `async/await` sözdizimi, Promise'ler üzerinde daha okunabilir ve senkron görünümlü kod yazmamızı sağlar. Aslında `async/await`, Promise'ler üzerinde bir 'sentaktik şeker'dir ve altında yine Promise'leri kullanır. Bu sayede, uzun Promise zincirlerini daha lineer bir akışla yazabiliriz.

Kod:
async function fetchUserDataAndPosts() {
  try {
    const users = await fetchData('https://api.example.com/users-async'); // await, Promise çözülene kadar bekler
    console.log(users);

    const posts = await fetchData('https://api.example.com/posts-async');
    console.log(posts);

    console.log('[b]Async/Await ile tüm veriler başarıyla alındı.[/b]');
  } catch (error) {
    console.error('[u]Async/Await hatası:[/u]', error.message);
  }
}

fetchUserDataAndPosts();

Sonuç

promise_flow.png


Resim: Promise akış şeması (temsili)

Promise API, JavaScript'teki asenkron programlamayı kökten değiştiren ve modern web geliştirmenin temel taşlarından biri haline gelen güçlü bir yapıdır. Callback hell sorununu çözmekle kalmayıp, kodu daha okunaklı, bakımı kolay ve hatalara karşı daha dirençli hale getirir. `Promise.all`, `Promise.race`, `Promise.allSettled` ve `Promise.any` gibi gelişmiş metotlar, karmaşık asenkron senaryoları yönetmek için esneklik sunar. `async/await` ile birleştiğinde ise, asenkron kod yazımı neredeyse senkron kod kadar anlaşılır hale gelir. Bu konuyu daha derinlemesine incelemek için MDN Promise belgesini ziyaret edebilirsiniz. Promise'lere hakim olmak, modern JavaScript geliştiricisinin olmazsa olmazıdır.

Umarım bu kapsamlı rehber, Promise API'nin gücünü ve kullanımını anlamanıza yardımcı olmuştur. İyi kodlamalar!
 
shape1
shape2
shape3
shape4
shape5
shape6
Üst

Bu web sitenin performansı Hazal Host tarafından sağlanmaktadır.

YazilimForum.com.tr internet sitesi, 5651 sayılı Kanun’un 2. maddesinin 1. fıkrasının (m) bendi ve aynı Kanun’un 5. maddesi kapsamında Yer Sağlayıcı konumundadır. Sitede yer alan içerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır.

YazilimForum.com.tr, kullanıcılar tarafından paylaşılan içeriklerin doğruluğunu, güncelliğini veya hukuka uygunluğunu garanti etmez ve içeriklerin kontrolü veya araştırılması ile yükümlü değildir. Kullanıcılar, paylaştıkları içeriklerden tamamen kendileri sorumludur.

Hukuka aykırı içerikleri fark ettiğinizde lütfen bize bildirin: lydexcoding@gmail.com

Sitemiz, kullanıcıların paylaştığı içerik ve bilgileri 6698 sayılı KVKK kapsamında işlemektedir. Kullanıcılar, kişisel verileriyle ilgili haklarını KVKK Politikası sayfasından inceleyebilir.

Sitede yer alan reklamlar veya üçüncü taraf bağlantılar için YazilimForum.com.tr herhangi bir sorumluluk kabul etmez.

Sitemizi kullanarak Forum Kuralları’nı kabul etmiş sayılırsınız.

DMCA.com Protection Status Copyrighted.com Registered & Protected