MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Generarea erorilor și operatorul throw

Interpretorul JavaScript generează erori pentru diverse situații, cum ar fi apelul unei funcții inexistente, reatribuirea unei constante etc. Cu toate acestea, în caz de necesitate, putem genera manual erori și să definim condițiile în care va apărea o eroare.

De exemplu, să examinăm următoarea situație:

class Person{
 
   constructor(name, age){
       this.name = name;
       this.age = age;
   }
   print(){ console.log(`Name: ${this.name}  Age: ${this.age}`);}
}
const tom = new Person("Tom", -123);
tom.print();    // Name: Tom  Age: -123

Clasa Person descrie o persoană. În constructorul clasei, se primesc valori pentru proprietățile name (nume) și age (vârstă).

Din punct de vedere logic, înțelegem că vârsta nu poate fi negativă. Cu toate acestea, până în acest moment, din perspectiva logică a clasei, nu există nimic care să împiedice transmiterea unei valori negative pentru vârstă la crearea unui obiect Person.

Din perspectiva interpretorului JavaScript, nu există nicio eroare, dar din perspectivă logică și de bun simț, aceasta este o eroare. Cum se poate remedia această situație? Există diverse modalități, iar una dintre ele constă în generarea unei excepții.

Pentru a genera o excepție, se folosește operatorul throw, după care se specifică informațiile despre eroare:

throw informatie_despre_eroare;

Informațiile despre eroare pot fi reprezentate de orice obiect.

Astfel, vom genera o excepție atunci când se furnizează o valoare negativă pentru proprietatea age în constructorul clasei Person:

class Person {
   constructor(name, age) {
       if (age < 0) throw "Vârsta trebuie să fie pozitivă";
       this.name = name;
       this.age = age;
   }

   print() {
       console.log(`Name: ${this.name}  Age: ${this.age}`);
   }
}

try {
   const tom = new Person("Tom", -123);  // Uncaught Vârsta trebuie să fie pozitivă
   tom.print();
} catch (eroare) {
   console.error(eroare);
}

În final, la apelul constructorului Person va fi generată o excepție și programul se va încheia cu o eroare. Pe consola browser-ului vom vedea informații despre eroare, care sunt specificate după operatorul throw:

Uncaught Vârstă trebuie să fie pozitivă

Ca și în cazul general, putem trata această eroare folosind blocul try...catch.

class Person {
 
   constructor(name, age) {
       if (age < 0) throw "Vârsta trebuie să fie pozitivă";
       this.name = name;
       this.age = age;
   }

   print() { console.log(`Name: ${this.name}  Age: ${this.age}`); }
}

try {
   const tom = new Person("Tom", -123);  // Uncaught Vârsta trebuie să fie pozitivă
   tom.print();
} catch (eroare) {
   console.log("A apărut o eroare");
   console.log(eroare);     // Vârsta trebuie să fie pozitivă
}

throw în try...catch...finally

Operatorul throw poate fi apelat în diferite contexte, de exemplu, în același bloc try:

try {
   throw "Eroare neașteptată!";
} catch (eroare) {
   console.log(eroare); // Eroare neașteptată!
}

Aceasta poate fi utilă din mai multe motive. În primul rând, putem gestiona eroarea imediat aici. În al doilea rând, putem defini cu ajutorul blocului finally unele acțiuni finale, care vor fi efectuate chiar dacă apare o eroare. De exemplu:

// Clasa bazei de date condiționale
class Database{
   constructor(){
       this.data = ["Tom", "Sam", "Bob"];
   }
   // Obținerea datelor
   getItem(index){
       this.open();
       if(index > 0 && index < this.data.length)
           return this.data[index];
       else
           throw "Index incorect";
       this.close();   // Această linie nu va fi executată în cazul generării unei excepții
   }
   // Deschiderea bazei de date
   open(){ console.log("Conexiunea la baza de date a fost stabilită"); }
   // Închiderea bazei de date
   close(){ console.log("Conexiunea la baza de date a fost închisă"); }
}

const db = new Database();
try {
   db.getItem(5);   // Returnăm elementul obținut
} catch(err) {
   console.error(err); // În cazul unei erori, o gestionăm
}

Aici este definită clasa Database - o clasă pentru o bază de date condiționată. Toate datele sunt stocate într-un array numit data. Pentru interacțiunea cu baza de date sunt definite trei metode.

Metodele open și close deschid și, respectiv, închid conexiunea cu baza de date. Metoda getItem primește un element din array-ul data pe baza unui index. În cazul în care indexul este incorect, se generează o eroare.

În acest context, înainte de a obține elementul prin index, metoda getItem ar trebui să deschidă conexiunea cu open și să o închidă după obținere cu close. Cu toate acestea, în exemplul de mai sus, în cazul generării unei erori, închiderea conexiunii nu va avea loc:

else
   throw "Index incorect";
this.close();   // în cazul generării unei excepții, această linie nu va fi executată

În consecință, atunci când se furnizează un index incorect la metoda getItem, output-ul consolei programului va fi următorul:

Conexiunea la baza de date a fost stabilită

Index incorect

Cu toate acestea, ce să facem dacă totuși dorim să apelăm metoda close? Putem plasa apelul în blocul finally:

class Database {
   constructor() {
       this.data = ["Tom", "Sam", "Bob"];
   }
   // Obținerea datelor
   getItem(index) {
       this.open();
       try {
           if (index > 0 && index < this.data.length)
               return this.data[index];
           else
               throw "Index incorect";
       } finally {    // chiar și dacă apare o eroare, acest bloc se va executa
           this.close();   // în cazul generării unei excepții, această linie totuși va fi executată
       }
   }
   // Deschiderea bazei de date
   open() { console.log("Conexiunea la baza de date a fost stabilită"); }
   // Închiderea bazei de date
   close() { console.log("Conexiunea la baza de date a fost închisă"); }
}

const db = new Database();
try {
   db.getItem(5);   // Returnăm elementul obținut
} catch (err) {
   console.error(err); // În cazul unei erori, o gestionăm
}

Acum, în cazul unei erori sau fără erori, blocul finally se va executa întotdeauna, asigurându-se că conexiunea la baza de date este închisă. Astfel, output-ul consolei va fi:

Conexiunea la baza de date a fost stabilită
Conexiunea la baza de date a fost închisă
Index incorect
← Lecția anterioară Lecția următoare →