Ce face async*
async* este varianta asincronă a lui sync*: funcția întoarce un Stream, adică o succesiune de valori care sosesc în timp. Fiecare yield trimite un eveniment ascultătorilor, iar între ele funcția poate aștepta cu await (o pauză, un fișier, o cerere).
Stream-ul pornește doar când cineva îl ascultă (await for sau listen). Când funcția se termină, stream-ul se închide. O excepție aruncată în ea ajunge ca eroare la ascultător.
Dacă ascultătorul se oprește (de exemplu cu break într-un await for), generatorul se oprește și el la următorul yield. yield* retrimite toate evenimentele altui stream.
Exemple
Exemplul 1: Numărătoare inversă
Câte un număr la fiecare 200 ms; await for le primește pe măsură ce apar.
Stream<int> numaratoare(int de) async* {
for (var i = de; i > 0; i--) {
await Future.delayed(const Duration(milliseconds: 200));
yield i;
}
}
Future<void> main() async {
print('Lansarea rachetei:');
await for (final n in numaratoare(3)) {
print('$n...');
}
print('Start!');
}
Rezultat
Lansarea rachetei:
3...
2...
1...
Start!
Exemplul 2: Transformarea unui alt stream
Generatorul citește comenzile dintr-un stream și trimite mai departe doar pe cele mari, cu un mesaj.
Stream<double> comenzi() => Stream.fromIterable([45.0, 320.5, 89.9, 1200.0]);
Stream<String> comenziMari(Stream<double> sursa) async* {
await for (final valoare in sursa) {
if (valoare >= 300) {
yield 'Comandă mare: $valoare lei';
}
}
}
Future<void> main() async {
await for (final mesaj in comenziMari(comenzi())) {
print(mesaj);
}
}
Rezultat
Comandă mare: 320.5 lei
Comandă mare: 1200.0 lei
Exemplul 3: Erori din generator
După al doilea senzor, generatorul aruncă o excepție; ea ajunge în catch-ul ascultătorului.
Stream<String> citesteSenzori() async* {
yield 'Senzor 1: 21.5 °C';
yield 'Senzor 2: 22.0 °C';
throw StateError('senzorul 3 nu răspunde');
}
Future<void> main() async {
try {
await for (final citire in citesteSenzori()) {
print(citire);
}
} on StateError catch (e) {
print('Oprit: ${e.message}');
}
}
Rezultat
Senzor 1: 21.5 °C
Senzor 2: 22.0 °C
Oprit: senzorul 3 nu răspunde
Greșeli frecvente
- Să întorci
Future<...>dintr-o funcțieasync*: tipul trebuie să fieStream<...>. return valoare;înasync*: nu este permis, foloseșteyield.- Să aștepți rezultate fără să asculți stream-ul: generatorul nu pornește până nu apare un ascultător.
Comenzi înrudite
await for: Parcurge un Stream element cu element, așteptând fiecare eveniment; se termină când stream-ul se închide.sync* și yield: O funcție sync* este un generator: produce elementele unui Iterable unul câte unul, cu yield, doar când sunt cerute.async și await: async marchează o funcție asincronă (întoarce Future), iar await așteaptă rezultatul unui Future fără să blocheze programul.