Promise, asenkron JavaScript programlama için bir kavramdır ve bir işlemin başarısız veya başarılı olduğu durumlarda sonuçlanan bir objedir Promise objesi oluşturmak için new Promise yöntemi kullanılır ve içinde resolve ve reject fonksiyonları bulunur Promise'lerin en önemli özelliklerinden biri de zincirleme yapabilme imkanıdır ve Nodejs'in async yapılarıyla birlikte kullanıldığında oldukça güçlü ve kullanışlı hale gelirler Promise'lerin kullanımı hataların kusursuz bir şekilde yönetilmesini sağlar ve then/catch blokları sayesinde farklı promise objelerini birleştirerek, işlemleri zincirleyebilir ve hepsinin sonucunu ayrı ayrı yakalayabiliriz
Promise, asenkron javascript programlama için kullanılan bir kavramdır. Asenkron programlama, işlemlerin arkaplanda devam etmesini sağlayarak, kullanıcının beklemesi gereken işlemleri engeller. Promise objesi, bir işlemin başarılı bir şekilde tamamlandığı veya başarısız olduğu durumlarda sonuçlanan bir objedir.
Bir promise objesi üretmek için new Promise() fonksiyonu kullanılır. İçerisinde fulfill(resolve) ve reject fonksiyonları bulunur. Fulfill fonksiyonu, işlem başarılı olduğunda promise'yi sonuçlandırır. Reject fonksiyonu ise işlem başarısız olduğunda promise'yi reddeder.
Promise'lerin en önemli özelliklerinden birisi de zincirleme yapabilme imkanıdır. Birçok promise objesi kullanarak zincirleme yapılabilir. Bu sayede önce bir işlem yapılır, ardından diğer işlemler sırasıyla gerçekleştirilir.
Promise'ler, özellikle Node.js'in async yapısıyla birlikte kullanıldığında oldukça güçlü ve kullanışlı hale gelirler. Birçok fonksiyonun promise dönmesi sayesinde kodda düzenli ve okunaklı bir yapı oluşturulabilir. Promise'ler, birden fazla objeyle çalışıldığında Promise.all() ve Promise.race() metotları kullanılabilir. Promise.all() metodu, birden fazla promise objesi için sonuçlarının birleştirilerek tek bir sonuç döndürür. Promise.race() metodu ise birden fazla promise objesi için yarışarak en hızlı sonucu döndürür.
Promise kullanımının en önemli amaçlarından birisi de hataların kusursuz bir şekilde yönetilmesidir. Promiseler, catch blokları sayesinde herhangi bir hata durumunda kurtarma imkanı sunarlar ve kodların daha verimli çalışmasını sağlarlar.
Promise Nasıl Kullanılır?
Promise, asenkron işlemler için kullanılan bir JavaScript nesnesidir. Promise objesi, bir işlemi yapmak için başlatılan bir fonksiyonu temsil eder ve bu fonksiyon asenkron bir şekilde çalışır. Promise'ler, bir işlemin başarılı bir şekilde tamamlanması durumunda bir sonuç döndürür ya da başarısız olması durumunda bir hata fırlatır.
Promise objesi oluşturmak için new Promise() yöntemi kullanılır. Bu yöntemle, bir fonksiyon içinde işlem yapılır ve işlemin sonucu, resolve() ya da reject() fonksiyonlarıyla geri döndürülür. Resolve() fonksiyonu, işlem başarılı bir şekilde tamamlandığında returnede bir veri dönmesini sağlar. Reject() fonksiyonu ise işlemde bir hata oluşması durumunda hatayı yakalar ve fırlatır.
Promise objesini oluşturduktan sonra, then() ve catch() fonksiyonları kullanılarak sonucu yakalayabilirsiniz. Then() fonksiyonu, işlemin başarılı bir şekilde tamamlanması durumunda geri dönen sonucu yakalar. Catch() fonksiyonu ise işlemin başarısız olması durumunda yakalanan hatayı işler. Örneğin, aşağıdaki kod bloğunda bir XMLHttpRequest işlemi promise objesi ile yapılmıştır:
new Promise(function(resolve, reject) { var xhr = new XMLHttpRequest(); xhr.open('GET', 'example.com', true); xhr.onload = function() { if (xhr.status == 200) { resolve(xhr.response); } else { reject(Error(xhr.statusText)); } }; xhr.onerror = function() { reject(Error("Network Error")); }; xhr.send();}).then(function(response) { console.log("Başarılı: ", response);}).catch(function(error) { console.error("Hata: ", error);});
Yukarıdaki örnekte, XMLHttpRequest işlemi promise objesi ile yapılmıştır. İşlemin sonucu, resolve() fonksiyonuyla başarılı durumda döndürülür ve then() fonksiyonu çalışır. Hatalı durumda ise reject() fonksiyonu kullanılarak hata yakalanır ve catch() fonksiyonu çalışır.
Promise'lerin en önemli özelliklerinden biri, then() ve catch() fonksiyonları arasındaki zincirli kullanımdır. Bu sayede, farklı promise objelerini birleştirerek, işlemleri zincirleyebilir ve hepsinin sonucunu ayrı ayrı yakalayabiliriz.
Yukarıdaki örnek kod bloğunda, bir XMLHttpRequest işlemi kullanıldı. Ancak, Node.js'de birçok HTTP işlemi promise objesi kullanarak yapılabilir. Promise objelerinin kullanımı, Node.js'in async yapılarıyla birlikte daha güçlü ve verimli bir şekilde kullanılabilir.
Promise objelerinin kullanımı, özellikle asenkron işlemlerde çok önemlidir ve kodlarımızın daha okunaklı ve anlaşılır şekilde yazılmasını sağlar. Çoklu işlemler için promise zincirleme, birden fazla promise objesinin sonucun birleştirilmesi için Promise.all() metodu ve promise'lerin yarıştırılması için Promise.race() metodları kullanılabilir.
Then/Catch Kullanımı
Promise objeleri then/catch blokları içinde kullanılarak oluşturulur. Bu blokların arasındaki fark, then bloğu bir promise objesi başarılı olduğunda çalışırken, catch bloğu başarısız olduğunda çalışır.
Then bloğu içindeki işlem başarılıysa, resolve(callback) fonksiyonu verilen callback fonksiyonunu çalıştırır ve verilen parametreleri döndürür. Eğer işlem başarısız olduysa, reject(err) fonksiyonu verilen err parametresini döndürür ve catch bloğuna yönlendirilir.
Catch bloğu ise promise objesi başarısız olduğunda çalışır ve hata ile ilgili bilgileri döndürür. Bu blok, hataların ele alınması için önemlidir ve programların çökmesini önler.
Örneğin, kullanıcı adı ve şifresi istenilen bir login işleminde, then bloğu başarılı login işlemi sonrası kullanıcıya hoş geldin mesajı gösterirken, catch bloğu yanlış kullanıcı adı veya şifre gibi bir hata durumunda kullanıcıya hata mesajı gösterir.
Ayrıca, birden fazla then bloku da kullanılabilir. Bu durumda, bir önceki then bloğunun döndürdüğü değer, bir sonraki then bloğunun parametresine girdi olarak verilir. Böylece, işlemler zinciri oluşturularak sonucun kontrolü daha kolay hale getirilmiş olur.
```let promise1 = new Promise((resolve, reject) =>{ setTimeout(resolve, 1000, "Merhaba");});
let promise2 = new Promise((resolve, reject) =>{ setTimeout(resolve, 1000, "Dünya");});
promise1.then(value => { console.log(value); return promise2;}).then(value => { console.log(value);});```Yukarıdaki örnekte, promise1 objesi 1 saniye sonra sonuç döndürür ve then bloğu içindeki console.log("Merhaba") çalışır. Daha sonra, promise1 objesi promise2 objesi ile değiştirilir ve promise2 objesi 1 saniye sonra sonuç döndürür ve diğer then bloğu içindeki console.log("Dünya") çalışır.
Eğer bir hata meydana gelirse, catch bloğu ile hata ele alınır. Örneğin, promise objesi oluşturma işlemi sırasında bir hata meydana gelirse, catch bloğu ile bu hata ele alınarak programın çökmesi engellenir.
```new Promise(function(resolve, reject) { throw new Error("Bu bir hata mesajıdır!");}).catch(function(err) { console.log(err.message);});```
Yukarıdaki örnekte, promise objesi oluşturma işlemi sırasında hata meydana gelir ve catch bloğu ile hata ele alınarak konsol ekranına hata mesajı yazdırılır. Bu şekilde, programın hata anında kesintiye uğraması engellenmiş olur.
Promise Zincirleme
Promise zincirleme, birden fazla promise objesi kullanarak tek bir işlemi sırayla gerçekleştirmek için kullanılan bir yöntemdir. Bu, özellikle bir işlemin sonucuna bağımlı olan ancak sırayla gerçekleştirilmesi gereken işlemlerde oldukça yararlıdır.
Bir promise objesi, bir işlemi gerçekleştirirken geriye döndürülecek olan sonucu temsil eder. Promise objeleri, then() metodunu kullanarak zincirlenebilirler. Bu metodun içindeki fonksiyon, önceki promise'in sonucunu kullanır ve yeni bir promise döndürür. Bu şekilde birden fazla promise objesi birbirleriyle zincirlenebilir.
Aşağıdaki örnek, fetch() metodunu kullanarak bir API'den verileri getirir ve ardından bu veriler üzerinde işlem yapar. İlk promise objesi, verileri getirmek için kullanılırken diğer promise objeleri, bu verilere göre işlem yapmak için kullanılır.
```jsfetch('https://example.com/data').then(response => response.json()).then(data => { return new Promise((resolve, reject) => { let newData = data.map(item => { // veri işleme işlemi return item; }); if(newData.length > 0) { resolve(newData); } else { reject('Veri bulunamadı'); } });}).then(newData => { // yeni verilerle işlem yapma}).catch(error => console.log(error));```
Yukarıdaki örnek, fetch() metodunu kullanarak verileri alır ve sonrasında bu verileri bir map fonksiyonu ile işler. Eğer veri bulunamazsa reject() metodu ile hata fırlatılırken, eğer veriler başarılı bir şekilde işlendiyse resolve() metodu ile yeni bir promise döndürülür. Daha sonra, bu yeni promise ile işlem yapılmak üzere yeni bir then() metodu kullanılır.
Promise zincirleme, özellikle JavaScript'te async/await yapısının olmadığı eski sürümlerde oldukça yaygın bir yöntemdi. Ancak günümüzde async/await ile birlikte kullanılan ve daha kolay bir şekilde yazılabilen bir yapıdır.
Node.js'te Promise Kullanımı
Node.js, JavaScript dili üzerine kurulu hızlı, hafif ve eşzamanlı bir platformdur. Async yapı, Node.js'in en önemli özelliklerinden biridir ve işlemlerin senkronize bir şekilde gerçekleştirilmesini engeller. Bu sayede, yüksek performanslı uygulamalar geliştirmek mümkün hale gelir.
Promise'ler, Node.js'in async yapısıyla uyumlu bir şekilde çalışır ve bu yapının kullanımını daha da kolaylaştırır. Promise, asenkron bir işlemin başarılı veya başarısız sonuçlarını temsil eden bir objedir. Promise objesinin içinde then ve catch fonksiyonları kullanılarak, işlemin sonucuna göre farklı işlemler yapılabilir.
Örnek olarak, bir dosya okuma işlemini asenkron olarak gerçekleştirmek istediğimizde, dosyanın okunması başarılı olduğunda then fonksiyonuna, başarısız olduğunda ise catch fonksiyonuna gidilir. Bu sayede, işlem sonucuna göre farklı hatalar veya başarılı sonuçlar işlenebilir.
Promise'lerin, birden fazla asenkron işlemi sırayla veya eş zamanlı olarak gerçekleştirmek için de kullanılabilir. Promise.all metodu, birden fazla promise objesinin sonuçlarını birleştirerek, tüm işlemlerin tamamlanmasını bekler. Promise.race metodu ise birden fazla promise objesinin yarışmasını sağlar ve ilk tamamlanan işlemin sonucunu döndürür.
Node.js'te Promise kullanımı, asenkron işlemleri kolay ve hızlı bir şekilde yönetmek için önemlidir. Promise'ler, async yapısına uyumlu olması sayesinde Node.js'in en önemli özelliklerinden biri olmuştur.
Promise All
Promise objeleriyle ilgili işlemlerinizde, birden fazla promise objesiyle çalışmanız gerekebilir. Bu durumda tüm promise'lerin başarılı bir şekilde sonuçlanmasını beklemek yerine, birleştirip tek bir sonuç almak daha mantıklı olabilir. İşte Promise.all metodu da tam olarak bunun için kullanılır.
Promise.all metodu, birden fazla promise objesinin sonuçlarını tek bir dizi içinde birleştirir ve aynı sırayla sunar. Bu sayede tüm promise'ler tamamlandığında tek bir işlemle sonuca erişebilirsiniz. Ayrıca, bu metot aynı zamanda tüm promise'lerin tamamlanması beklenirken geçen zamanı da minimize eder.
Tabii ki, tüm promise'lerin tamamlanması beklenirken geçen süre bu metotla birlikte daha da uzun olabilir. Ancak, her bir promise objesi farklı bir işlem yaparken, bu işlemler birbiriyle bağımsız olduklarından aynı anda yürütülerek sürenin kısaltılması olasıdır.
Şimdi bir örnek üzerinden Promise.all metodu kullanımını ele alalım. Aşağıda görüldüğü gibi, bir ödeme formu oluşturulmuştur ve ödeme işlemi için kullanıcının hesap bilgilerinin doğru olup olmadığı kontrol edilir.
Alan Adı | Kontrol Edildi mi? |
---|---|
Ad Soyad | Promise |
Kredi Kartı Numarası | Promise |
Son Kullanma Tarihi | Promise |
CVC Kodu | Promise |
Her bir alan için bir promise objesi oluşturabilir ve bunları Promise.all metoduyla birleştirebiliriz.
const kontrolPromise1 = new Promise((resolve, reject) => { const adSoyad = document.querySelector("#ad-soyad").value; if (adSoyad && adSoyad.trim() !== "") { resolve(adSoyad); } else { reject("Lütfen ad soyadınızı girin."); }});const kontrolPromise2 = new Promise((resolve, reject) => { const kartNo = document.querySelector("#kart-no").value; if (kartNo && kartNo.trim().length === 16) { resolve(kartNo); } else { reject("Lütfen geçerli bir kredi kartı numarası girin."); }});
const kontrolPromise3 = new Promise((resolve, reject) => { const sonKullanma = document.querySelector("#son-kullanma").value; if (sonKullanma && sonKullanma.trim().length === 7) { resolve(sonKullanma); } else { reject("Lütfen geçerli bir son kullanma tarihi girin."); }});
const kontrolPromise4 = new Promise((resolve, reject) => { const cvcKodu = document.querySelector("#cvc-kodu").value; if (cvcKodu && cvcKodu.trim().length === 3) { resolve(cvcKodu); } else { reject("Lütfen geçerli bir CVC kodu girin."); }});
Promise.all([kontrolPromise1, kontrolPromise2, kontrolPromise3, kontrolPromise4]) .then(degerler => { alert("Ödeme işlemi başarıyla gerçekleştirildi."); }) .catch(error => { alert("Bir sorun oluştu: " + error); });
Yukarıdaki örnekte, her bir alan için bir promise objesi oluşturduk ve bunları Promise.all metoduyla birleştirdik. Bu sayede, tüm promise'lerin tamamlanması beklenerek ödeme işlemi gerçekleştirildi.
Promise Race
Promise objelerinin yarışması, bir fonksiyonun birden fazla farklı veri kaynağından veri alması gerektiğinde oldukça kullanışlıdır. Bu durumu farklı promise objelerini oluşturarak çözmek mümkündür. Promise race metodu, birden fazla promise objesi arasında bir yarış düzenler. Bu yarışta hangi promise objesi önce işlemi tamamlarsa, race metodu da o promise objesinin sonucunu döndürür.
Örneğin, bir uygulamanın farklı veri kaynaklarından veri alması gerektiğini düşünelim. Bu durumda bu veri kaynaklarından farklı promise objeleri oluşturabilir ve bunları promise race metodu içerisinde yarıştırabiliriz. İşlem tamamlandığında, hangi promise objesi daha hızlı işlem tamamlayacaksa, race metodu o objenin sonucunu döndürecektir.
Aşağıda, iki farklı veri kaynağından veri alınması gereken bir örneği ele alalım:
```javascriptconst promise1 = new Promise((resolve, reject) =>{ setTimeout(()=>{ resolve('Promise 1 sonucu'); }, 3000);});
const promise2 = new Promise((resolve, reject) =>{ setTimeout(()=>{ resolve('Promise 2 sonucu'); }, 2000);});
Promise.race([promise1, promise2]).then(result => console.log(result));```
Yukarıdaki örnekte, promise1 ve promise2 adında iki farklı promise objesi oluşturduk. İlk obje 3 saniye, ikinci obje ise 2 saniye bekledikten sonra sonuç döndürüyor. Promise.race metodu, bu iki obje arasında bir yarış düzenliyor ve hangisi daha hızlı sonuç döndürecekse o objenin sonucunu dönüyor.
Sonuç olarak, promise race metodu sayesinde birden fazla farklı promise objesi arasında bir yarış düzenleyebilir ve hangi objenin daha hızlı işlem tamamlayacağını belirleyerek işlemleri optimize edebiliriz.
Promise Hataları
Promise'lerde, birkaç hata meydana gelebilir. Bu hatalar, promise zincirlemesinin yürütülmesini engelleyebilir veya beklenenden farklı sonuçlar doğurabilir. Promiselerde en sık karşılaşılan hataların bazıları şunlardır:
- TypeError: Promise objeleri, işlemler sırasında bazı hatalarla karşılaşabilir. Bu hatalar, TypeError hatası ile sonuçlanabilir. Bu tip hatalar, genellikle yanlış bir tip dönüşümü ya da bir değişkenin değerinin null ya da undefined olması sonucu ortaya çıkar. Örneğin:
var promise = Promise.resolve(10); promise.then(function(resolve) { resolve.toUpperCase(); });
function myPromise() { return Promise.reject("Error"); } myPromise() .then( function(result) { console.log(result); }) .catch( function(error) { console.log(error); })
function myPromise() { return new Promise(function(resolve,reject) { reject("Error1"); reject("Error2"); }); } myPromise() .then( function(result) { console.log(result); }) .catch( function(error) { console.log(error); })
Bu hataların önüne geçmek için, sürekli olarak catch() metodu ile hata elde edilebilir. Ayrıca, bir try-catch bloğu kullanarak hatanın sebebini inceleyebilir ve çözüme ulaştırabilirsiniz.