Lidando com Erros e a Pilha de Chamadas de Funções - JavaScript
Quando um erro ocorre dentro de uma função e não é tratado, o interpretador de JavaScript sai dessa função e busca um tratador de erros no código externo. Veja o exemplo a seguir:
function A() {
console.log("func A starts");
callSomeFunc();
console.log("func A ends");
}
A()
console.log("program ends");
Neste caso, a função A
callSomeFunc()
A
try
catch
A
func A starts Uncaught ReferenceError: callSomeFunc is not defined at A (index.html:11:2) at index.html:30:6
O mesmo se aplica a chamadas de funções aninhadas. Se um erro ocorre em uma função interna e não é tratado, o interpretador também sai para o contexto externo, a função externa. Se o erro também não for tratado na função externa, o interpretador continua buscando até encontrar um tratador de erros. Se não encontrar nenhum tratador de erro em nenhuma função nem no código global, o programa termina. Por exemplo:
function A() {
console.log("func A starts");
callSomeFunc();
console.log("func A ends");
}
function B() {
console.log("func B starts");
A();
console.log("func B ends");
}
function C() {
console.log("func C starts");
B();
console.log("func C ends");
}
C();
console.log("program ends");
Aqui, a função C
B
A
callSomeFunc
A
A
B
C
func C starts func B starts func A starts Uncaught ReferenceError: callSomeFunc is not defined at A (index.html:11:2) at B (index.html:16:2) at C (index.html:27:2) at index.html:31:1
Agora, vamos definir um tratador de erros em uma das funções, por exemplo, na função C
function A() {
console.log("func A starts");
callSomeFunc();
console.log("func A ends");
}
function B() {
console.log("func B starts");
A();
console.log("func B ends");
}
function C() {
console.log("func C starts");
try {
B();
}
catch {
console.log("Error occured");
}
console.log("func C ends");
}
C();
console.log("program ends");
Com a introdução do tratador de erros, o interpretador primeiro busca um tratador na função A
B
C
func C starts func B starts func A starts Error occured func C ends program ends
Dessa forma, as funções A
B
Propagando Erros pela Pilha de Chamadas de Funções
Às vezes, erros são tratados em algum lugar dentro das chamadas aninhadas de outras funções. Vamos considerar a seguinte situação:
// classe de um banco de dados fictício
class Database {
constructor() {
this.data = ["Tom", "Sam", "Bob"];
}
// método para obter dados
getItem(index) {
if (index >= 0 && index < this.data.length)
return this.data[index];
else // se o índice for inválido, lançamos um erro
throw new RangeError("Invalid index");
}
// método para abrir o banco de dados
open() {
console.log("Database has opened");
}
// método para fechar o banco de dados
close() {
console.log("Database has closed");
}
}
// função para obter um objeto do banco de dados pelo índice
function get(index) {
const db = new Database();
db.open(); // simulamos a abertura do banco de dados
try {
return db.getItem(index); // retornamos o elemento obtido
} catch(err) {
console.error(err); // se ocorrer um erro, tratamos aqui
throw err; // lançamos o erro novamente para ser tratado mais acima na pilha
} finally {
db.close(); // simulamos o fechamento do banco de dados
}
}
// função para exibir o resultado
function printResult() {
try {
const item = get(5); // tentamos obter o elemento com índice 5
console.log("Got from database:", item); // exibimos o elemento obtido
} catch(err) {
console.error("Error during database retrieval:", err); // tratamos o erro aqui
}
}
printResult();
Este exemplo define uma classe Database
open
close
getItem
RangeError
A função get
Database
printResult
O uso do bloco finally
A saída do console será:
Database has opened Error during database retrieval: RangeError: Invalid index at Database.getItem Database has closed Error during database retrieval: RangeError: Invalid index