Atualizado: 07/12/2024

Lançando Erros com o Operador throw - JavaScript

O interpretador de JavaScript lança erros para diversas situações, como ao chamar uma função inexistente ou ao tentar reatribuir um valor a uma constante. No entanto, também podemos lançar nossos próprios erros e definir condições sob as quais os erros serão lançados.

Por exemplo, considere a seguinte situação:

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

A classe Person descreve uma pessoa. O construtor da classe recebe valores para as propriedades name (nome) e age (idade). É de senso comum que a idade não pode ser negativa. No entanto, de acordo com a lógica da classe, nada impede que um objeto Person seja criado com um valor negativo para idade. Do ponto de vista do interpretador JavaScript não há erro, mas segundo a lógica e o bom senso, isso é um erro. Como podemos corrigir essa situação? Existem várias maneiras, e uma delas é lançando uma exceção.

Para lançar uma exceção, usamos o operador throw, após o qual especificamos informações sobre o erro:

throw informacaoSobreErro;

As informações sobre o erro podem ser representadas por qualquer objeto.

Então, vamos lançar uma exceção quando um valor negativo for passado para a propriedade age no construtor de Person:

class Person {
    constructor(name, age) {
        if (age < 0) throw "A idade deve ser positiva";
        this.name = name;
        this.age = age;
    }
    print() { console.log(`Name: ${this.name} Age: ${this.age}`); }
}
try {
    const tom = new Person("Tom", -123);    // Uncaught A idade deve ser positiva
    tom.print();
} catch (error) {
    console.log("Ocorreu um erro");
    console.log(error);     // A idade deve ser positiva
}

Consequentemente, ao chamar o construtor de Person, será lançada uma exceção e o programa terminará com erro. A informação sobre o erro, que foi especificada após o operador throw, aparecerá na console do navegador:

Uncaught A idade deve ser positiva

Como em casos gerais, podemos lidar com esse erro usando um bloco try...catch.

Uso do throw em try..catch..finally

O operador throw pode ser chamado em diferentes contextos, como dentro de um bloco try. Isso pode ser útil por várias razões. Em primeiro lugar, podemos lidar imediatamente com o erro. Em segundo lugar, podemos usar o bloco finally para definir algumas ações finais que serão executadas, mesmo que um erro seja lançado. Por exemplo:

// classe de um banco de dados fictício
class Database {
    constructor() {
        this.data = ["Tom", "Sam", "Bob"];
    }
    // obter dados
    getItem(index) { 
        this.open();
        if(index > 0 && index < this.data.length)
            return this.data[index];
        else
            throw "Índice incorreto";
        this.close();   // essa linha não será executada se uma exceção for lançada
    }
    // abrir o banco de dados
    open() { console.log("Conexão com o banco de dados estabelecida"); }
    // fechar o banco de dados
    close() { console.log("Conexão com o banco de dados fechada"); }
}
    
const db = new Database();
try {
    db.getItem(5);   // retorna o elemento obtido
} catch(err) {
    console.error(err); // se ocorrer um erro, tratamos aqui
}

Neste trecho, a classe Database é uma classe de um banco de dados fictício. Todos os dados são armazenados em um array data. Para interagir com o banco de dados, três métodos são definidos. Os métodos open e close abrem e fecham a conexão com o banco de dados, respectivamente. O método getItem recupera um elemento do array data por índice. Se o índice for incorreto, um erro é lançado. Antes de recuperar o elemento por índice, o método getItem deve abrir a conexão com o método open, e após recuperar o elemento, fechar com o método close. No entanto, no exemplo acima, se um erro for lançado, o fechamento da conexão não ocorrerá:

else
    throw "Índice incorreto";
this.close();   // essa linha não será executada se uma exceção for lançada

Consequentemente, se um índice incorreto for passado ao método getItem, o output da console será:

Conexão com o banco de dados estabelecida
Índice incorreto

Mas o que fazer se ainda precisarmos chamar o método close? Podemos colocar sua chamada no bloco finally:

class Database {
    constructor() {
        this.data = ["Tom", "Sam", "Bob"];
    }
    // obter dados
    getItem(index) { 
        this.open();
        try {
             if(index > 0 && index < this.data.length)
                return this.data[index];
            else
                throw "Índice incorreto";
        }
        finally {    // mesmo que um erro seja lançado, este bloco é executado
            this.close();   // essa linha será executada mesmo se uma exceção for lançada
        }
    }
    // abrir o banco de dados
    open() { console.log("Conexão com o banco de dados estabelecida"); }
    // fechar o banco de dados
    close() { console.log("Conexão com o banco de dados fechada"); }
}
 
const db = new Database();
try {
    db.getItem(5);   // retorna o elemento obtido
} catch(err) {
    console.error(err); // se ocorrer um erro, tratamos aqui 
}

E agora o output da console será diferente:

Conexão com o banco de dados estabelecida
Conexão com o banco de dados fechada
Índice incorreto
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com