async și await în Dart

async marchează o funcție asincronă (întoarce Future), iar await așteaptă rezultatul unui Future fără să blocheze programul.

Sintaxă
Future<Tip> functie() async {
  final rezultat = await altaFunctie();   // așteaptă fără să blocheze programul
  return valoare;                         // devine Future<Tip>
}

Ce face async și await

Operațiile care durează (citirea unui fișier, o cerere pe internet, o pauză) întorc un Future: o promisiune că valoarea va veni mai târziu. Într-o funcție marcată async, await pune funcția pe pauză până când Future-ul este gata și dă direct valoarea, iar codul se citește de sus în jos, ca un cod obișnuit.

O funcție async întoarce mereu un Future: dacă scrii return 5; într-o funcție Future<int> ... async, apelantul primește un Future<int>. Cât timp funcția așteaptă, programul poate face alte lucruri; Dart are un singur fir de execuție, dar nu stă blocat.

Erorile dintr-un Future așteptat cu await se prind cu try/catch, ca orice excepție. Pentru mai multe operații independente, pornește-le pe toate și așteaptă-le împreună cu Future.wait, ca să nu aștepți pe rând.

Exemple

Exemplul 1: Așteptarea unui rezultat

Future.delayed simulează o operație lentă. Mesajul „Aștept…” apare înainte, pentru că main continuă până la await.

Future<double> cursEuro() async {
  await Future.delayed(const Duration(milliseconds: 300));
  return 4.97;
}

Future<void> main() async {
  print('Aștept cursul...');
  final curs = await cursEuro();
  print('1 EUR = $curs lei');
  print('100 EUR = ${(100 * curs).toStringAsFixed(2)} lei');
}

Rezultat

Aștept cursul...
1 EUR = 4.97 lei
100 EUR = 497.00 lei

Exemplul 2: Erori prinse cu try/catch

Excepția aruncată în funcția asincronă ajunge la await și este prinsă normal.

Future<int> stocProdus(String cod) async {
  await Future.delayed(const Duration(milliseconds: 100));
  const stoc = {'CAF01': 12, 'LAP02': 0};
  final cantitate = stoc[cod];
  if (cantitate == null) throw StateError('produsul $cod nu există');
  return cantitate;
}

Future<void> main() async {
  for (final cod in ['CAF01', 'XYZ99']) {
    try {
      print('$cod: ${await stocProdus(cod)} bucăți');
    } on StateError catch (e) {
      print('Eroare: ${e.message}');
    }
  }
}

Rezultat

CAF01: 12 bucăți
Eroare: produsul XYZ99 nu există

Exemplul 3: Mai multe operații în paralel

Cu Future.wait, cele trei așteptări se suprapun: totalul durează cât cea mai lungă (aprox. 300 ms), nu cât suma lor. Rezultatele vin în ordinea din listă.

Future<String> temperatura(String oras, int ms, int grade) async {
  await Future.delayed(Duration(milliseconds: ms));
  print('  a răspuns $oras');
  return '$oras: $grade °C';
}

Future<void> main() async {
  final ceas = Stopwatch()..start();
  final rezultate = await Future.wait([
    temperatura('Iași', 300, 14),
    temperatura('Oradea', 100, 17),
    temperatura('Constanța', 200, 19),
  ]);
  print(rezultate);
  print('Sub 600 ms? ${ceas.elapsedMilliseconds < 600}');
}

Rezultat

  a răspuns Oradea
  a răspuns Constanța
  a răspuns Iași
[Iași: 14 °C, Oradea: 17 °C, Constanța: 19 °C]
Sub 600 ms? true

Greșeli frecvente

  • await într-o funcție fără async: eroarea The await expression can only be used in an async function.
  • Apelul unei funcții asincrone fără await: primești un Future, nu valoarea, iar erorile ei nu mai sunt prinse de try.
  • await într-o buclă pentru operații independente: se execută pe rând. Folosește Future.wait.

Comenzi înrudite

  • await for: Parcurge un Stream element cu element, așteptând fiecare eveniment; se termină când stream-ul se închide.
  • async*: O funcție async* produce un Stream: trimite valori cu yield, în timp, și poate folosi await între ele.
  • main: Funcția de la care pornește orice program Dart; poate primi argumentele din linia de comandă.
  • try, catch și finally: try prinde excepțiile din bloc; on alege tipul, catch dă acces la obiect, finally rulează mereu.