await for în Dart

Parcurge un Stream element cu element, așteptând fiecare eveniment; se termină când stream-ul se închide.

Sintaxă
await for (final element in stream) {
  ...        // rulează pentru fiecare eveniment, pe măsură ce sosește
}

Ce face await for

await for este bucla for-in pentru stream-uri. Pentru fiecare valoare care sosește, corpul buclei rulează o dată; între valori, funcția așteaptă fără să blocheze programul. Bucla se termină când stream-ul se închide.

Ca orice await, poate fi folosit doar într-o funcție async sau async*. break și return opresc ascultarea (abonamentul este anulat), iar o eroare din stream se aruncă la bucla await for și se prinde cu try.

Nu folosi await for pe stream-uri care nu se închid niciodată (de exemplu clicurile dintr-o interfață), pentru că bucla nu se mai termină. Acolo se folosește stream.listen(...).

Exemple

Exemplul 1: Suma valorilor dintr-un stream

Stream.periodic produce o valoare la fiecare 100 ms; take(4) închide stream-ul după patru valori.

Future<void> main() async {
  final incasari = Stream.periodic(const Duration(milliseconds: 100), (i) => (i + 1) * 50).take(4);

  var total = 0;
  await for (final suma in incasari) {
    total += suma;
    print('Încasat $suma lei, total $total lei');
  }
  print('Ziua s-a încheiat.');
}

Rezultat

Încasat 50 lei, total 50 lei
Încasat 100 lei, total 150 lei
Încasat 150 lei, total 300 lei
Încasat 200 lei, total 500 lei
Ziua s-a încheiat.

Exemplul 2: Oprire cu break

Căutarea se oprește la primul rezultat găsit; restul stream-ului nu mai este citit.

Stream<String> clienti() async* {
  for (final nume in ['Ana', 'Bogdan', 'Cezar', 'Diana', 'Eugen']) {
    await Future.delayed(const Duration(milliseconds: 50));
    print('  (citesc $nume)');
    yield nume;
  }
}

Future<void> main() async {
  await for (final nume in clienti()) {
    if (nume.startsWith('C')) {
      print('Găsit: $nume');
      break;
    }
  }
  print('Căutare terminată.');
}

Rezultat

  (citesc Ana)
  (citesc Bogdan)
  (citesc Cezar)
Găsit: Cezar
Căutare terminată.

Exemplul 3: Liniile unui fișier

File.openRead dă un stream de octeți; după decodare și împărțire pe linii, fiecare linie se procesează pe rând, fără să încărcăm tot fișierul în memorie.

import 'dart:convert';
import 'dart:io';

Future<void> main() async {
  final fisier = File('vanzari.csv');
  await fisier.writeAsString('Cluj;1200\nIași;950\nSibiu;700\n');

  var total = 0;
  final linii = fisier.openRead().transform(utf8.decoder).transform(const LineSplitter());
  await for (final linie in linii) {
    final [oras, suma] = linie.split(';');
    total += int.parse(suma);
    print('$oras: $suma lei');
  }
  print('Total: $total lei');
}

Rezultat

Cluj: 1200 lei
Iași: 950 lei
Sibiu: 700 lei
Total: 2850 lei

Greșeli frecvente

  • await for într-o funcție fără async: eroare de compilare.
  • for (final x in stream) fără await: eroare, Stream nu este Iterable.
  • await for pe un stream infinit fără break sau take: codul de după buclă nu se mai execută.

Comenzi înrudite

  • async*: O funcție async* produce un Stream: trimite valori cu yield, în timp, și poate folosi await între ele.
  • async și await: async marchează o funcție asincronă (întoarce Future), iar await așteaptă rezultatul unui Future fără să blocheze programul.
  • for-in: Parcurge pe rând elementele unei liste, unui set sau oricărui Iterable, fără indice.
  • break și continue: break oprește bucla imediat; continue sare peste restul repetării curente și trece la următoarea.