Javascript Asenkron Programlama Promise Algoritmasi
08 Nov 2012Promise Monad’ı Nedir?
Promise, asenkron programlamanın temel taşlarından birisidir. İlk okuduğum kaynaklarda mantığını tam olarak anlamamış olsam da daha sonradan aslında pek de zor bir konu olmadığını öğrendim.
Promise’in en büyük özelliği fonksiyonel olması ve fonksyionel programlamada Monad olarak değerlendirilmesidir. (Nesnel düşünen yazılımcılar için anlaması cidden zor)
Promise, adı üzerinde “söz” bir fonksiyonun bir olayı gerçekleyeceğine söz vermesidir. Böylece asenkron bir yapı elde edebilirsiniz, burada tabii fonksiyonel programlamanın nimetlerinden de faydalanıyoruz; mesela fonksiyonların birinci sınıf vatandaş olması gibi.
Kendimizden örnek
Gerçek dünyadan bir promise örneği düşünelim;
“Ali ekmek alacak, Veli de süt alacak” gibi bir ilkokula giriş cümlesi ile başlayalım.
Bu cümlede Ali, bize ekmek alacağı sözünü veriyor; Veli ise süt alacağı sözünü veriyor.
“Ali ekmek alırsa, ona para veririm.”
“Veli süt alamazsa, ona çok kızarım.”
şeklinde iki adet de verilen sözlerin karşılığında yapılacak işleri düşünelim.
Sanki çok “if/else” gibi?
Evet, buraya kadar işler fazlasıyla “if” koşulu gibi duruyor, fakat “if” koşulu asenkron bir mantıkta çalışmaz. Ayrıca, bu çok fazla imperative bir yapıdır. Ayrıca asenkron değil. Dediğimiz gibi, fonksiyonların blocklara göre en önemli farkı daha sonradan kullanılabilir olmaları.
Bunu if ile yazsaydık;
Burada işlemlerin bitmesi gerektiğini görüyoruz; promise yapılarda bu işlerin bitmesi gerekmiyor. Her iş bitişi için bir promise return ediyoruz. Imperative değil fonksiyonel bir yapı elde ediyoruz.
Bunu asenkron düşündüğümüzde şöyle bir yapıda yazabiliriz;
If
koşullamasından biraz kurtulduk. Peki bu şekilde yazmak bize ne kazandırdı? Öncelikle, if
kullanmadığımız için, işlemin sonucunu beklemiyoruz, çok uzun sürse dahi.
Bunun yerine yapılacak işlemin sonucuna bağlı birer callback atıyoruz.
Monad: Promise
Evet, geldik işin en can alıcı kısmına. Bu fonksiyonlar .success
, .fail
gibi durumları nasıl dönüyorlar?
Cevap: promise ile. Bu fonksiyonlar, implemente edilirken, promise
dönecek şekilde yazılıyorlar.
Bakalım aliEkmekAlsin
fonksiyonumuz nasıl implemente edilmiş?
Evet! Ali bakkaldan ekmek alırsa, promise çözülsün (sözünü tutmuş olsun), yoksa promise iptal olsun (sözünü tutmadı :()
Ups! işler karıştı?
Hayır, karışmadı. Şimdi bunu daha çalışabilir bir hale getirelim:
O zaman bunu çalıştıracak promise sınıfımızın en ilkel halini yazalım:
Bütün temeli bu kadar. Gerçekten.
Şu an bir promise sınıfına sahibiz. Fakat biraz fazla yeteneksiz. Geliştireceğiz.
Öncelikle bunun bir hatası var, yalnızca bir success
callback’i alabiliyor. Bunu biraz daha birikebilir hale getirelim:
Evet işte oldu. Bu bizim promise algoritmamızın temelini oluşturuyor. Ve aslında çalışan bir promise algoritması. :)
Birden fazla deferred’i yönetmek
Evet, orası için de fikrimiz var.
Elimizde bir sürü deferred (promise dönen) nesne olsun;
diyerek alabilmeliyiz;
O halde hemen when algoritmasının en ilkel halini yazalım:
Biraz uzun oldu, ama en temel hali bu. Kısaca şunu yapıyor, her promise’a bir success callback atayıp, bu callback’lerin bir pointer’ı (resolved) bir artırıyor. Böylece kaç adet resolve olduğunu biliyoruz. Eğer resolved ile toplam promise sayısı eşit ise, bu işlem başarılı oluyor. Aksi halde başarısız olarak dönüyor.
artık çalışır durumda.
Fakat bu örnek yalnızca iki deferred için çalışıyor. O zaman bunu biraz daha dinamik yapalım.
Şimdi deneyelim:
Evet, çalışıyor. :)
Promise işleri bu kadar kolay. Tabii, bunun daha güçlü implementasyonlarını yazmak mümkün. Eğer jQuery kullanıyorsanız, hazır implemente edilmiş bir hali zaten var.
Fonksiyonel programlama ile ilgili kaynakları araştırmanızı da öneririm.