24- Dart future, async, await, then, catchError, whenComplete

Yazımızın içeriğini aşağıdan video olarak izleyebilirsiniz.

Dart Senkron – Asenkron Programlama Nedir?

Asenkron: başlama ve sona erme zamanları ayrı olan Senkron ise eşzamanlı olan anlamına gelmektedir.

Dart dilinde senkron bir yapı aynı anda sıra beklemeden bir çok kodun çalışabilmesidir. Asenkron durumda ise hepsi birbirini bekleyecektir.

Gelelim kodlarımıza nasıl çalışırlar?

void main(){

print ("Kod 1");
print ("Kod 2");
print ("Kod 3");

}
//SONUÇ
//Kod 1
//Kod 2
//Kod 3

Biz yukarıda ki gibi yazdığımızda hepsi sırası ile çalışacaktır. Önce Kod 1 yazacak, sonra Kod 2 ve en sonunda da Kod 3 yazacaktır.

Şimdi kendimizi gişesinde sadece bir görevli olan banka sırasında hayal edelim. Bir sıra numarası alırız ve sıramız gelince işlemimiz yapılır. Az önce yazdığımız kodlar da bu şekildeydi.

Biz sırada beklerken önümüzdekinin işi uzun sürerse onu beklemek zorundayız. Hatta önümüzdeki olurda gişedeki görevliyle kavga ederse orada bir kargaşa olur ve sistem durur. Geride sıra bekleyenlerin işi olmaz sistem çöker.

İşte düz mantık kodlar bu şekilde çalışır.

Keşke 2nci, 3ncü, 4ncü görevlilerde olsaydı. İşi uzun süreceklere ayrı ayrı baksalardı. Kimseyi sırada bekletmeselerdi.

İŞİN ÖZÜ BU ARKADAŞLAR. Senkron bir şekilde işi uzun sürecekleri (işlerinin ne kadar süreceği belli değil) ayrı baksalardı. Standart işler de diğer yandan yürüseydi.

Şimdi gelelim işin teknik kısmına;

Bu örneklerimizi kodlarımıza uygulamaya;

Tasarımımız ile ilgili bir senaryo oluşturalım;

İnternetten bir veri çekeceğiz ve onları bir listede göstereceğiz. Birde listenin altında açılacak olan butonlarımız, textlerimiz v.b. var.

Şimdi bizim textlerimizin, butonlarımızın yüklenmesi için internetten gelen veriyi bekleyelim mi? Bir loading atalım ve internetten verimiz gelene kadar program dönsün dursun, bu olmaz arkadaşlar. Ya internetten verimiz gelemezse, bir sorun oluşursa, bu sefer programımız takılır kalır. Geri kalan hiçbir şey çalışmaz.

O zaman biz öyle bir şey yapmalıyız ki internetten veri çekme işi ayrı diğer işler ayrı olsun. Programımız iki ayrı işlemi ayrı ayrı yapsın. Listemiz yüklenene kadar loading gözüksün ama bizim diğer işlemlerimiz onu beklemesin açılmaya devam etsin.

İşte bunun için dart yazılım dilinde future sınıfını kullanacağız. Future anlamı gelecek demek. Aslında isminden de anlaşıldığı üzere sen bu işlemi al gelecekte, yani işin bitince sonuçlandır. Ben de bu sırada diğer işlerimi halledeyim.

DİKKAT BUYURALIM;

Hatırlarsanız bizim geriye değer döndüren fonksiyonlarımız vardı. Bunu hatırlamak için en açık halinle aşağıya yazıyorum ve detaylara inmeye başlıyoruz.

//MAİNİN DIŞINDA KLASİK BİR FONKSİYON TANIMLADIK
//MAİNİN İÇERİSİNDE FONKSİYONUMUZA ERİŞTİK.

void main(List<String> args) {

  int hesaplananDeger = ornekFonksiyon(2, 4);
//fonksiyonumuzu çağırdık
//int tipinde geriye bir değer döndürdüğü için int tipinde bir değişkene aktardık
//ve yazdırdık

  print(hesaplananDeger);
}

int ornekFonksiyon(int a, int b) {
  int sonuc = a + b;
  return sonuc;

//int tipinde bir fonksiyondu
//geriye int tipinde return ettik
}

// SONUÇ
// 6
Dart-asenkron-programlama-02

Yukarıda tanımladığımız bu fonksiyonun aynısını aşağıda kısaltılmış hali ile yazalım. Bilen arkadaşlar burayı geçebilirler ancak daha sonra göreceklerimiz kafanızı karıştırmasın diye tekrar etmekte fayda gördüm.

//YUKARIDA TANIMLADIĞIMIZ ÖRNEĞİN AYNISI
//KISALTILMIŞ HALİ
//HATIRLAMA MAKSATLI

void main(List<String> args) {
  print(ornekFonksiyon(2, 4));
}

int ornekFonksiyon(int a, int b) => a + b;
//Süslü parantezi ve return ifadesini kaldırıp yerine 
//şişman ok (fat arrow) koyarak direkt return
//edeceğimiz değeri yazdık
//YANİ BİZ {return a+b;} yerine =>a+b; kullanabiliyoruz.
//Bir sonraki örneklerimizde isimsiz lambda fonksiyonlarda
//sıkça görücez. 

// SONUÇ
// 6

GELELİM ESAS MESELEYE;

Bu fonksiyon bize klasik int tipinde geriye bir değer döndürdü ve biz de onu return ettik. Biz bu işlem uzun süren bir işlem olsaydı programımızın diğer kodlarının çalışmasına devam etmesi için Future sınıfı kullanacaktık. Sen bu işlemi yap ama ne kadar sürecek, ne zaman bitecek ben bilmiyorum. Gelecekte bir zamanda bitecek. O zaman geriye klasik olarak int döndürmeyecek. Future<int> döndürecek. Bir future nasıl tanımlanır, geriye nasıl değer döndürür basit bir şekilde aşağıda örneklerle anlatalım.

Future, then, catchError, whenComplete

Dart Asenkron Programlama Future then catchError whenComplete async await
void main(List<String> args) {

  ornekFonksiyon(2, 4).then((gelecekDeger) => print(gelecekDeger));
  //then sonra demek. Fonksiyonumuzu çağırdık 
  //then içerisine isimsiz bir lamda fonksiyon alıyor
  //bizden bir değişken girmemizi bekliyor
  //ve gelen değere istediğimiz işlemi yapıp
  //return ile geri döndürdük
}

Future<int> ornekFonksiyon(int a, int b) => Future.value(a + b);
//Gelecekte int tipinde değer döndürecek bir fonksiyon tanımladık
//Bize işlemi bitince a+b yi döndürecek


// SONUÇ
// 6
dart-asenkron-programlama-04

Şimdi aşağıda bir senaryo üretelim, bankadayız ve sıra aldık bekliyoruz. 3 kişiyiz. Ben 3ncü kişiyim. Önümde 2 numaranın işi çok uzun. Bankadaki diğer görevli diyor ki sen buraya gel biz senin işini ayrı yapalım. Yoksa sıradakiler çok bekler.


void main(List<String> args) {

  print("******************");
  print("Lütfen Banka Sıra Numarası Alınız");
  print("******************");

  print("1nci sıradayım");
  ikinciSiradayim().then((gelecekDeger) => print(gelecekDeger));
  print("3ncü sıradayım");
}

//Aşağıda fonksiyonumu tanımladım. Geriye String döndüren bir Future.
//Gerçek gibi bir senaryo üretebilmek için Future sınıfının delay(gecikme) 
//fonksiyonunu kullanarak 3 sn gecikme ekledim.

Future<String> ikinciSiradayim() {
  return Future<String>.delayed(Duration(seconds: 3), () => "2nci sıradayım");
}

/*
SONUÇ
******************
Lütfen Banka Sıra Numarası Alınız
******************
1nci sıradayım
3ncü sıradayım
2nci sıradayım

*/
dart-asenkron-programlama-05

Aşağıdaki örnekte ilave olata catchError ve whenComplete kullanılmıştır. Bu yapıyı try catch bloklarına benzetebilirsiniz. Bir hata olduğunda catchError yapısı çalışacak, bir hata olsun olmasın whenComplete işlem bittiğinde default olarak çalışır.


void main(List<String> args) {

  print("******************");
  print("Lütfen Banka Sıra Numarası Alınız");
  print("******************");

  print("1nci sıradayım");
  ikinciSiradayim()
      .then((gelecekDeger) => print(gelecekDeger))
      .catchError((e) => print(e)) 
      .whenComplete(() => print("işlem başarılı"));
  print("3ncü sıradayım");
}

Future<String> ikinciSiradayim() {
  return Future<String>.delayed(Duration(seconds: 3), () => "2nci sıradayım");
}


/*
SONUÇ
******************
Lütfen Banka Sıra Numarası Alınız
******************
1nci sıradayım
3ncü sıradayım
2nci sıradayım
işlem başarılı


*/
dart-asenkron-programlama-06

ŞİMDİ İŞLERİ BİRAZ DEĞİŞTİRELİM;

İşler her zaman böyle gitmez; Bazen de biz bu kodları beklemek isteriz ve arkasından gelen işlemi Future işlemi bitmeden çalışsın istemeyiz. Burada banka örneğimizi unutuyoruz. Şöyle düşünelim mesela biz internetten veri alıyoruz ve gelen veri ile alt tarafta hesaplama yaptırıyoruz. O zaman bu gelecek olan Future mecbur beklenecek, yoksa gelmeden hesaplama yapmaya çalışır ve hata alırız.

Burada senaryomuza göre tercih yapıyoruz.

Future, async, await

async ingilizce asynchoronous un kısaltması. Asenkron demek. Yukarıda da tanımlamasını yaptığımız gibi Asenkron başlama ve sona erme zamanları ayrı olan Senkron ise eşzamanlı olan anlamına gelmektedir. await ise beklemek anlamına geliyor. Biz beklemek istediğimiz fonksiyonumuzun başına await yazarak işlemin bitmesini bekliyoruz. Geri kalan kodlarımız ondan sonra çalışıyor. Burada bir şart var await i nerede kullandıysak o fonksiyonun süslü parantezlerinden hemen önce async eklememiz gerekiyor. Aşağıda ki örneği inceleyelim.

void main(List<String> args) async {

  print("bir numara");

  print(await ikiNumara());
  //await deyerek işlemin bitmesini bekledik
 
  print("üç numara");
}

//fonksiyonumuzu tanımladık
Future<String> ikiNumara() {
  return Future<String>.delayed(Duration(seconds: 3), () => "iki numara");
}

/*
SONUÇ
bir numara
iki numara
üç numara
*/
dart-asenkron-programlama-06

Aşağıdaki örnekte bir Future tanımlayalım ve içerisine bir for döngüsü koyalım. Belirlediğimiz sayıya kadar olan sayıların toplamını geri döndürsün. İşlem uzun sürecektir. Bu future dan sonra birde print ile birşeyler yazdıralım. İki farklı şekilde örneğimizi yapalım.

//FUTURE KENARDA İŞİNİ YAPMAYA DEVAM ETTİ
//BU SIRADA PRİNT İÇERİSİNDEKİ İFADE YAZILDI
//EN SONUNDA FUTURE İŞİNİ BİTİRDİ VE SONUÇ VERDİ

void main(List<String> args) {

  Future<int>(() {
    int toplam = 0;
    for (var i = 0; i < 1000000000; i++) {
      toplam = i + toplam;
    }
    return toplam;
  }).then((value) => print(value));

  print("Ben aslında sonum");
}

/*
SONUÇ
Ben aslında sonum
499999999500000000
*/
dart-asenkron-programlama-08
//BU ÖRNEKTE İSE AWAIT KULLANDIK
//FUTURE UN İŞLEMİNİN BİTMESİNİ BEKLEDİ
//SONRA PRİNT YAZILDI

void main(List<String> args) async {
  await Future<int>(() {
    int toplam = 0;
    for (var i = 0; i < 1000000000; i++) {
      toplam = i + toplam;
    }
    return toplam;
  }).then((value) => print(value));

  print("Ben aslında sonum");
}
/*
SONUÇ
499999999500000000
Ben aslında sonum
*/
dart-asenkron-programlama-09

Aşağıda aynı örneği bir future değişkene atıp yapalım

//BU ÖRNEKTE İSE AWAIT KULLANDIK
//FUTURE UN İŞLEMİNİN BİTMESİNİ BEKLEDİ
//SONRA PRİNT YAZILDI


void main(List<String> args) async {
  Future<int> deger = Future<int>(() {
    int toplam = 0;
    for (var i = 0; i < 1000000000; i++) {
      toplam = i + toplam;
    }
    return toplam;
  });

  print(await deger);
  print("ben future u bekleyeceğim");
}

/*
SONUÇ
499999999500000000
ben future u bekleyeceğim

*/
dart-asenkron-programlama-10

“24- Dart future, async, await, then, catchError, whenComplete” için 4 yorum

    1. Teşekkür ederim, yılların verdiği yoğun iş temposundan sonra; ilgi duyanların yararlanması amacı ile yazdığım, yazarken keyif aldığım yazılar, gelen teşekkür mesajları mutlu olmamı sağlıyor…

Yorum bırakın

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