Tratamento de erros: try, catch, finally
Esta aula aborda o tratamento de erros em JavaScript usando try, catch e finally, incluindo o uso de throw, o objeto Error, os tipos de erro comuns e boas práticas para escrever código robusto.
O tratamento de erros é uma parte essencial do desenvolvimento de software. Em JavaScript, erros podem ocorrer durante a execução do código, seja por problemas de sintaxe, dados inválidos ou falhas externas. Para lidar com essas situações de forma controlada, a linguagem oferece as instruções try, catch e finally. Nesta aula, vamos explorar como usar essas estruturas para capturar e gerenciar erros, evitando que o programa quebre inesperadamente.
Além disso, veremos como lançar erros personalizados com throw, entender o objeto Error e seus subtipos, e adotar boas práticas para um tratamento de erros eficiente e legível.
throw
A instrução throw permite que você lance uma exceção personalizada. Quando uma exceção é lançada, a execução normal do código é interrompida e o controle é transferido para o bloco catch mais próximo. Você pode lançar qualquer valor: números, strings, objetos, mas é recomendável usar o objeto Error ou suas subclasses para manter a consistência.
Exemplo básico:
function dividir(a, b) {
if (b === 0) {
throw new Error('Divisão por zero não é permitida');
}
return a / b;
}
try {
let resultado = dividir(10, 0);
console.log(resultado);
} catch (erro) {
console.error('Erro capturado:', erro.message);
}
Neste exemplo, a função dividir verifica se o divisor é zero e lança um erro. O bloco try executa a função, e o catch captura o erro, exibindo a mensagem.
Objeto Error
O objeto Error é a base para todos os erros em JavaScript. Ele possui propriedades como name (tipo do erro) e message (descrição). Você pode criar instâncias personalizadas:
const erro = new Error('Algo deu errado');
console.log(erro.name); // "Error"
console.log(erro.message); // "Algo deu errado"
console.log(erro.stack); // stack trace (pilha de chamadas)
Além do Error genérico, existem subtipos como TypeError, RangeError, ReferenceError, etc. Eles herdam de Error e são usados para indicar tipos específicos de falhas.
Tipos de erro
JavaScript possui vários tipos de erro nativos, cada um indicando uma situação diferente:
- SyntaxError: Erro de sintaxe no código (ex: falta de parênteses).
- ReferenceError: Tentativa de acessar uma variável não definida.
- TypeError: Operação incompatível com o tipo (ex: chamar algo que não é função).
- RangeError: Valor fora do intervalo permitido (ex: array com tamanho negativo).
- URIError: Erro em funções de URI como
decodeURI().
Exemplo de TypeError:
try {
let num = 42;
num(); // TypeError: num is not a function
} catch (erro) {
if (erro instanceof TypeError) {
console.log('Erro de tipo:', erro.message);
} else {
console.log('Outro erro:', erro.message);
}
}
É importante verificar o tipo do erro no catch para tratar cada situação adequadamente.
Boas práticas
Ao trabalhar com tratamento de erros, siga estas recomendações:
- Sempre use objetos Error: Lance instâncias de
Errorou subclasses, nunca strings ou números. Isso fornece informações como stack trace. - Seja específico: Crie classes de erro personalizadas para diferentes cenários (ex:
ValidationError,DatabaseError). - Não engula erros: Evite blocos
catchvazios. Sempre registre ou trate o erro de alguma forma. - Use finally para limpeza: O bloco
finallyexecuta independentemente de erro, ideal para fechar conexões ou liberar recursos. - Evite try/catch em código síncrono desnecessário: Use apenas onde erros são esperados e possam ser recuperados.
Exemplo com finally:
function processarArquivo() {
let arquivo = null;
try {
arquivo = abrirArquivo('dados.txt');
// processa...
} catch (erro) {
console.error('Erro ao processar arquivo:', erro);
} finally {
if (arquivo) {
arquivo.fechar();
}
}
}
Referências
Exercícios
- Crie uma função que aceite um número e lance um erro se o valor for negativo. Use try/catch para testar.
- Escreva um código que force um ReferenceError e o trate exibindo uma mensagem personalizada.
- Crie uma classe de erro personalizada chamada ValidationError que herde de Error. Use-a em uma função de validação de email.
- Use o bloco finally para garantir que uma mensagem de "Fim da operação" seja sempre exibida, independentemente de erro.
- Escreva um código que demonstre o uso de try/catch aninhado, capturando erros em diferentes níveis.
function verificarPositivo(num) {
if (num < 0) {
throw new Error('Número não pode ser negativo');
}
return num;
}
try {
console.log(verificarPositivo(-5));
} catch (erro) {
console.error(erro.message);
}
try {
console.log(variavelInexistente);
} catch (erro) {
if (erro instanceof ReferenceError) {
console.log('Variável não definida:', erro.message);
} else {
throw erro;
}
}
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
function validarEmail(email) {
if (!email.includes('@')) {
throw new ValidationError('Email inválido: falta @');
}
return true;
}
try {
validarEmail('usuario.com');
} catch (erro) {
if (erro instanceof ValidationError) {
console.error('Erro de validação:', erro.message);
} else {
console.error('Outro erro:', erro);
}
}
try {
console.log('Tentando executar...');
throw new Error('Algo deu errado');
} catch (erro) {
console.error('Erro:', erro.message);
} finally {
console.log('Fim da operação');
}
try {
try {
let obj = null;
obj.prop; // TypeError
} catch (erroInterno) {
console.log('Erro interno capturado:', erroInterno.message);
throw new Error('Erro relançado');
}
} catch (erroExterno) {
console.log('Erro externo capturado:', erroExterno.message);
}