Dart Asenkron Programlama
Published: 2023-01-05 14:49:24

Asenkron programlama genellikle callback fonksiyonlarını kullanır, ancak Dart Future ve Stream nesnelerini de alternatif olarak kullanıma sunar.
Future , gelecekte bir zamanda sağlanacak bir sonuç için verilen söz gibidir. Stream , olaylar(events) gibi bir dizi değer almanın bir yoludur.


Not: Her zaman Future veya Stream API'lerini doğrudan kullanmanız gerekmez. Dart dili, async ve await gibi anahtar sözcükleri kullanarak da asenkron kodlamayı destekler.


## Future:

Future  objeler, genellikle asenkron bir method tarafından döndürülen nesne olarak Dart kitaplıklarında görünür. Bir future tamamlandığında, değeri kullanıma hazırdır.

### await kullanımı:
Kodunuzun anlaşılabilirliğinin daha kolay olması açısından Future apisini kullanmak yerine await kullanmayı düşünün. 

Aşağıdaki method arka arkaya üç asenkron methodu yürütmek için Future'ın then() methodunu kullanır ve bir sonrakini yürütmeden önce her birinin tamamlanmasını bekler.


```
void runUsingFuture() {
  // ...
  findEntryPoint().then((entryPoint) {
    return runExecutable(entryPoint, args);
  }).then(flushThenExit);
}
```

Await ifadelerine sahip eşdeğer kod, daha çok senkronize kod gibi görünür:

```
Future<void> runUsingAsyncAwait() async {
  // ...
  var entryPoint = await findEntryPoint();
  var exitCode = await runExecutable(entryPoint, args);
  await flushThenExit(exitCode);
}
```

Asenkron bir fonksiyon, Vadeli İşlemlerden exception'ları yakalayabilir. Örneğin:

```
var entryPoint = await findEntryPoint();
try {
  var exitCode = await runExecutable(entryPoint, args);
  await flushThenExit(exitCode);
} catch (e) {
  // Handle the error...
}
```

Gelecek tamamlandığında çalışacak kodu programlamak için then() öğesini kullanabilirsiniz. Örneğin, HTTP istekleri biraz zaman alabileceğinden, HttpRequest.getString() bir Future döndürür. then() işlevinin kullanılması, aşağıdaki örnekteki gibi Future tamamlandığında ve vaat edilen string değeri kullanılabilir olduğunda bazı kodlar çalıştırmanıza izin verir:

```
HttpRequest.getString(url).then((String result) {
  print(result);
});
```

Bir Future nesnesinin oluşturabileceği hataları veya istisnaları işlemek için catchError() öğesini kullanın.

Not: catchError() işlevini, then() öğesinin sonucunda çağırdığınızdan emin olun.



```
Future result = costlyQuery(url);
result
    .then((value) => expensiveWork(value))
    .then((_) => lengthyComputation())
    .then((_) => print('Done!'))
    .catchError((exception) {
  /* Handle exception... */
});
```

Yukarıdaki örnekte, yöntemler aşağıdaki sırayla çalışır:

1. costlyQuery()
2. expensiveWork()
3. lengthyComputation()


Aynı kodu aşağıdaki gibi await kullanarak da yazabilirsiniz:

```
try {
  final value = await costlyQuery(url);
  await expensiveWork(value);
  await lengthyComputation();
  print('Done!');
} catch (e) {
  /* Handle exception... */
}
```


Bazen algoritmanızın birçok asenkron işlevi çağırması ve devam etmeden önce hepsinin tamamlanmasını beklemesi gerekir. Birden çok vadeli fonksiyonu yönetmek için Future.wait() statik methodunu kullanın ve bunların tamamlanmasını bekleyin:


```
Future<void> deleteLotsOfFiles() async =>  ...
Future<void> copyLotsOfFiles() async =>  ...
Future<void> checksumLotsOfOtherFiles() async =>  ...

await Future.wait([
  deleteLotsOfFiles(),
  copyLotsOfFiles(),
  checksumLotsOfOtherFiles(),
]);
print('Done with all the long steps!');
```

## Stream

Stream  nesneleri, veri dizilerini temsil eden Dart API'lerinde görünür. Örneğin, button tıklamaları gibi HTML olayları, akışlar(streams) kullanılarak iletilir. Bir dosyayı stream olarak da okuyabilirsiniz.


### Asenkron bir for döngüsü kullanma

```
void main(List<String> arguments) async {
  // ...
  if (await FileSystemEntity.isDirectory(searchPath)) {
    final startingDir = Directory(searchPath);
    await for (final entity in startingDir.list()) {
      if (entity is File) {
        searchFile(entity, searchTerms);
      }
    }
  } else {
    searchFile(File(searchPath), searchTerms);
  }
}
```

Önemli: Await for'u kullanmadan önce kodu daha anlaşılır hale getirdiğinden ve akışın(stream) tüm sonuçlarını gerçekten beklemek istediğinizden emin olun. DOM event listener'ları için await for kullanmamalısınız, çünkü DOM sonsuz olay akışları gönderir. Arka arkaya iki DOM olay dinleyicisini(event listener) kaydetmek için wait for'u kullanırsanız, ikinci tür olay asla işlenmez.



Kaynak:
https://dart.dev/guides/libraries/library-tour#dartasync---asynchronous-programming