rethrow în Dart

Excepții Dart 1.0

Aruncă mai departe excepția prinsă în catch, păstrând stiva de apeluri originală.

Sintaxă
try {
  ...
} catch (e) {
  // jurnalizare, curățenie...
  rethrow;
}

Ce face rethrow

rethrow; se poate scrie doar într-un bloc catch. El aruncă mai departe exact aceeași excepție, ca și cum nu ar fi fost prinsă, iar funcția care te-a apelat o poate trata.

Se folosește când vrei să faci ceva la apariția erorii (să scrii în jurnal, să anulezi o operație), dar decizia finală aparține altui nivel din program. Spre deosebire de throw e;, rethrow păstrează stiva de apeluri originală, deci vezi locul unde a apărut problema.

Poți combina: prinzi un tip, tratezi unele cazuri și faci rethrow pentru celelalte.

Exemple

Exemplul 1: Jurnalizare și aruncare mai departe

incarcaProfil scrie în jurnal, iar main decide ce afișează utilizatorului.

int citesteVarsta(String text) {
  try {
    return int.parse(text);
  } on FormatException {
    print('[jurnal] vârstă invalidă: "$text"');
    rethrow;
  }
}

void main() {
  try {
    print(citesteVarsta('23'));
    print(citesteVarsta('douăzeci'));
  } on FormatException catch (e) {
    print('Utilizatorului: introdu un număr (${e.message})');
  }
}

Rezultat

23
[jurnal] vârstă invalidă: "douăzeci"
Utilizatorului: introdu un număr (Invalid radix-10 number)

Exemplul 2: Tratezi unele cazuri, restul merg mai departe

Codul 404 este tratat local; celelalte erori sunt aruncate mai departe.

class EroareHttp implements Exception {
  final int cod;
  EroareHttp(this.cod);
  @override
  String toString() => 'EroareHttp $cod';
}

String descarca(String pagina) {
  final coduri = {'acasa': 200, 'vechi': 404, 'admin': 403};
  final cod = coduri[pagina] ?? 500;
  if (cod != 200) throw EroareHttp(cod);
  return 'conținutul paginii $pagina';
}

String descarcaSauGol(String pagina) {
  try {
    return descarca(pagina);
  } on EroareHttp catch (e) {
    if (e.cod == 404) return '(pagina nu mai există)';
    rethrow;
  }
}

void main() {
  for (final p in ['acasa', 'vechi', 'admin']) {
    try {
      print(descarcaSauGol(p));
    } on EroareHttp catch (e) {
      print('Eroare netratată: $e');
    }
  }
}

Rezultat

conținutul paginii acasa
(pagina nu mai există)
Eroare netratată: EroareHttp 403

Exemplul 3: rethrow păstrează stiva originală

Stiva arată funcția calculeaza, unde a apărut eroarea, nu locul unde a fost aruncată din nou.

int calculeaza(List<int> v) => v[10];

int cuJurnal(List<int> v) {
  try {
    return calculeaza(v);
  } catch (e) {
    print('[jurnal] ${e.runtimeType}');
    rethrow;
  }
}

void main() {
  try {
    cuJurnal([1, 2, 3]);
  } catch (e, s) {
    final functii = s
        .toString()
        .split('\n')
        .where((l) => l.contains('main.dart'))
        .map((l) => l.split(RegExp(r'\s+'))[1]);
    print('Stiva: ${functii.join(' <- ')}');
  }
}

Rezultat

[jurnal] RangeError
Stiva: calculeaza <- cuJurnal <- main

Greșeli frecvente

  • rethrow în afara unui catch: A rethrow must be inside of a catch clause.
  • throw e; în loc de rethrow;: stiva începe din blocul catch, iar locul real al erorii se pierde.
  • Prinderea și aruncarea mai departe fără să faci nimic: atunci try-catch nu are rost.

Comenzi înrudite

  • try, catch și finally: try prinde excepțiile din bloc; on alege tipul, catch dă acces la obiect, finally rulează mereu.
  • throw: Aruncă o excepție sau o eroare care oprește execuția normală până o prinde un catch.