Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

ECMAScript 6 – Async / Await Keywordleri

Merhaba,

Bu makalemizde JavaScript’in doğal olan asenkron yapısına karşı hakimiyet sağlamamıza yarayan Async ve Await keywordleri üzerine konuşuyor olacağız.

İlk olarak yukarıda da bahsedildiği gibi JavaScript’in asenkron yapısı üzerine konuşalım.
JavaScript anatomik olarak asenkron yapıya sahip script dilidir. Yani çağrılan fonksiyonları satır satır işlememekte bilakis asenkron temelli paralel bir çalışma sergilemektedir ve çıktıları işlem sıralamasından ziyade yapılan işlemlerin süreleri baz alınarak belirlemektedir.

let metot1 = () => {
    console.log("metot1");
};
let metot2 = () => {
    console.log("metot2");
};
let metot3 = () => {
    console.log("metot3");
};
metot1();
metot2();
metot3();

Yukarıdaki kod bloğunu incelerseniz eğer sırasıyla “metot1”, “metot2” ve “metot3” çağrılmakta ve bu süreç asenkron bir şekilde ceyran etmektedir. Çıktı olarak ise sırasıyla;
metot1
metot2
metot3

sonucu alınmaktadır.
La hoca bunun neresi asenkron layn?” diyenleriniz olabilir. Tabi burada fonksiyonlarımızın işlev maliyetleri neredeyse yok denecek kadar az olduğundan ve işlev süreleri ise mikrosaniye cinsinden hemen hemen birbirlerine yakın olduğundan çıktı olarak çağrılma sırasına uygun bir şekilde sonuçlar elde edilmiştir. Ama aşağıdaki gibi fonksiyonların işlev süreleriyle oynarsak;

let metot1 = () => {
    setTimeout(() => {
        console.log("metot1");
    }, 5000);
};
let metot2 = () => {
    setTimeout(() => {
        console.log("metot2");
    }, 3000);
};
let metot3 = () => {
    setTimeout(() => {
        console.log("metot3");
    }, 4000);
};
metot1();
metot2();
metot3();

çıktı olarak;
metot2
metot3
metot1

sonucunu verecektir. Neden mi? “metot1″in beş saniye, “metot2″nin üç saniye ve “metot3″ün dört saniye işlev süresi vardır. Dolayısıyla süreç asenkron işleyeceğinden dolayı tüm metotlar aynı anda paralel bir şekilde tetiklenecek ve işlev süresi kısa olan öncelikli çıktı verecektir. Nedeni budur…

Peki hoca bu fonksiyonları bir başka fonksiyon içerisinde çağırsak… O zaman senkron olmaz mı?” diye söylediğinizi duyar gibiyim. Eee hadi dediğinizi uygulayıp, beraber inceleyelim.

let metot4 = () => {
    metot1();
    metot2();
    metot3();
};
metot4();

Yukarıdaki gibi oluşturduğumuz fonksiyonu çağırdığımızda gene benzer sonuçla karşılaşıyoruz.
metot2
metot3
metot1

Hatta araya farklı işlemler tıkıştırıp deneyelim;

let metot4 = () => {
    metot1();
    console.log("ara işlem 1");
    metot2();
    console.log("ara işlem 2");
    metot3();
};

metot4();

ara işlem 1
ara işlem 2
metot2
metot3
metot1

Yok! Nuh diyor, peygamber demiyor…

Eee, peki bu durumda ne yapıyoruz hoca?
Eskiden metotlarımızı callback fonksiyonlara çevirerek öncelikleri zahmetli bir şekilde belirtebiliyorduk. Tabi sonraki süreçlerde aynı mantıkta callback fonksiyonlarını pratik kullanabilmek için geliştirilmiş Promise Yapısını kullanarak çalışmalarımızı icra ediyorduk.

Promise yapısını kullanarak süreci nasıl senkron hale getirdiğimizi inceleyelim.

let metot1 = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("metot1");
            resolve("");
        }, 5000);
    });
};
let metot2 = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("metot2");
            resolve("");
        }, 3000);
    });
};
let metot3 = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("metot3");
            resolve("");
        }, 4000);
    });
};

Fonksiyonlarımızı Promise yapısına çevirdikten sonra aşağıdaki gibi kullanabilmekteyiz;

metot1().then(() =>
    metot2().then(() =>
        metot3().then()
    )
);

İşte bu şekilde kullandığımızda metotlarımız belirtilen sırada tetikleneceğinden dolayı sistem senkron işlemiş olacaktır ve beklenen çıktı alınacaktır.
metot1
metot2
metot3

La hoca, biz JavaScript’te senkron çalışmak için bunca uğraşa mecburmuyuz?” diye serzenişte bulunduğunuzu da duyar gibiyim. Durun… Hemen yelkenleri suya indirmeyin. Bu içeriği boşuna yazmıyoruz 🙂 Tabi ki de gelecek vaadeden bir dil kendindeki bu aksaklığı daha pratik bir şekilde çözüme kavuşturmak için çabalayacaktır. Dolayısıyla ECMAScript çabalamış ve netice olarak async ve await keywordleri ile süreci senkron hale getirme imkanı tanımıştır.

Burada C# ile bir kıyas yapmak istiyorum. C#, özü itibariyle senkron bir programlama dilidir. Lakin asenkron programalama yapabilmek için birçok yöntem arasında async ve await komutları kullanılır. async ile işaretlenmiş metot içerisinde asenkron bir işlem uygulanacağı metoda bildirilir ve await keywordü ile de hangi işlem olduğu işaretlenir. Yani C#’ta async ve await keywordleri senkron çalışmayı asenkron hale getirmektedir.

ECMAScript’te ise durum tam tersidir. Özü itibariyle asenkron olan bir dildeki işleyişi senkron gibi yönetebilmek için yine async ve await keywordleri kullanılır.

ECMAScript’te async ve await keywordlerini kullanırken dikkat etmeniz gerekenler;

  • Kullanılacak fonksiyon async ile işaretlenip metot içerisinde asenkron bir işlem olacağı bildirilmelidir,
  • await ile işaretlenecek olan fonksiyon geriye Promise nesnesi döndürmelidir,
  • Örneklerde kullanmadık lakin sizler kesinlikle try – catch yapısı eşliğinde kontrol mekanizmasında çalışınız,
  • await keywordüne null değerini verirseniz bir hataya neden olmamaktadır,
  • await keywordüne Promise nesnesi haricinde bir değer verirsek direkt olarak pass(geç) edecektir. Benzer mantıkla geriye Promise dönmeyen herhangi bir fonksiyon verirseniz eğer gene pass işlemine tabi tutulacaktır.

Yukarıda metotların tanımlandığı en sonuncu Promise geri dönüşlü hallerini baz alarak aşağıdaki gibi async ve await keywordlerini kullanabiliriz.

async function executeAsync() {
    await metot1();
    await metot2();
    await metot3();
}
executeAsync();

Süreç senkron işleyeceğinden dolayı çıktı beklendiği gibi olacaktır.

Evet… Bir yazımızın daha sonuna gelmiş bulunmaktayız. Bol bol faydalanmanız dileğiyle…

Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

6 Cevaplar

  1. Efe dedi ki:

    `“metot1”, “metot2” ve “metot3” çağrılmakta ve bu süreç asenkron bir şekilde ceyran etmektedir` diyerek metodların asenkron cagrıldığını soylemişsiniz ama yanlışınız var orada fonksiyonların senkron cağırımı var. İşlem maliyeti filan demişsiniz ama method1 5 sn method 2 3 method 4 sn işlemlik bir süre alsa da sırayla işlem bitimine kadar çağrılacaktır.

    2. örneğinizde setTimeout asenkron çalışan bir yapı olduğundan methodlar asenkron gibi çalışsada aslında method senkron çağırılıyor. Asenkron çağrılan setTimeout içindeki fonksiyondur. Orneğin method1 hata fırlatsa method2 ve 3 çalışmayacaktır cunku senkron. Yazınız yanlış bilgi vermektedir.

    • Gençay dedi ki:

      Noktasından virgülüne kadar dokunmadan yayınlıyorum. İlgilenenler bu farklı yorumu, yapılan yargıya takılmaksızın mukayese amaçlı değerlendirebilirler.
      Sevgiler…

    • Gençay dedi ki:

      Değerli okuyucularım;

      Efe’nin yapmış olduğu yoruma nazaran iş arkadaşlarımla yaptığım istişare neticesinde haklı olduğuna dair kanaate varmış bulunmaktayız.

      Bahsedilen ibarede asenkron değil senkron bir seyr söz konusudur. Lakin setTimeout fonksiyonu bu şekilde kullanıldığı zaman farklı Thread’lar da işlevsellik göstereceklerinden dolayı asenkron izlenimde bir çalışma sergilemektedirler. İşte makalemizin konusu bu tarz bir durumda dahi(yani farklı threadların söz konusu olduğu esnada) akışı kontrol edebilmek ve promise tarzında sıralı işlev ile süreci geçirmek için ilgili makalenin içeriği ele alınmıştır.

      Arkadaşın yorumuna karşı yapılan tepkisel yaklaşımdan dolayı özür dilerim…

      Sevgiler…

  2. Mustafa dedi ki:

    Öncelikle yıllar geçmiş olsa bile :)) yazınız gerçekten harika bir ders niteliğinde. Benim aşırı işime yaradı ve anlaşılır. Ellerinize yüreğinize sağlık.
    İkinci olarak ise bir arkadaş simüle ettiğiniz durumu dile ana yapısına monte etmişsiniz gibi yaklaşmış ama tabi ki benzetim kullanırken terimsel ifadeler iç içe geçiyor. Çağrı gene de senkronize yapılsa bile benzetim bile olsa fonksiyonlar asenkron çalışmış oluyor.

    Size ve itiraz eden arkadaşa da selamlar. Bu arada keşke daha yapıcı bir yorum yapsaydı. İnsanların yazıyı okumasını engelleyebilir halbuki çok çok basit şekilde örneklenmiş çözümler var.

    • Gençay dedi ki:

      Merhaba,

      Öncelikle güzel yorumunuz için teşekkür ederim.

      Şahsen özgürce yapılan eleştiri, fikir yahut düşüncelerin yayınlanmasından doğacak önyargı ne o yorumu yapanın ne de benim sorumluluğumda olacaktır. Kişi buna aldanıp içeriğe göz atmaktan cayıyorsa bu zayıflıktır. Sırf bu zayıflıktan kaçınmak için gelen özgür bir eleştiriyi kaldırmaktansa o kişinin okumamasını tercih ederim 🙂

      Sevgiler…

  3. Abdullah Yıldız dedi ki:

    Hocam paylaşım için çok teşekkürler, bende single thread synchronous çalışan bir dil olduğunu düşünerek yazıyı okumama rağmen bu güne kadar kafamda hep bir karışıklara sebeb olan şeylerin pekişmesine sebep oldu. Bence bu konudaki karışıklık birazda Türkçe deki senkron ifadesinin farklı anlaşılmasından kaynaklanıyor. Sıralı işlem, eş zamanlı işlem felan diye yazılınca daha anlaşılır oluyor. Yazıyı ve yorumu olduğu gibi paylaşmanız çok faydalı olmuş, teşekkürler…

Abdullah Yıldız için bir yanıt yazın Yanıtı iptal et

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir