Como usar try…catch em JavaScript
Aprenda a usar try...catch em JavaScript para lidar com erros e melhorar a experiência do usuário.
Construir aplicações JavaScript envolve antecipar e lidar com problemas inesperados. Os erros são inevitáveis, mas gerenciá-los efetivamente garante uma melhor experiência do usuário. O JavaScript oferece o bloco try…catch como uma maneira estruturada de lidar com erros de forma elegante.

Este artigo explora como usar o bloco try…catch, abordando sua sintaxe básica e cenários avançados, como blocos aninhados, lançamento de erros e tratamento de código assíncrono.
A sintaxe básica de try...catch
A instrução try...catch consiste em três partes principais:
- Um bloco
try— Contém o código que pode gerar um erro - Um bloco
catch— Lida com um erro se ocorrer. É executado apenas quando um erro é gerado - Um bloco
finally— Executa o código de limpeza. Ele é executado independentemente de um erro ser gerado ou não
O bloco try deve ser seguido por um bloco catch ou finally, ou ambos, como mostrado abaixo:
// try...catch
try{
console.log("executando bloco try...")
console.log(missingVar)
}catch{
console.log("ocorreu um erro")
}
// SAÍDA:
// executando bloco try...
// ocorreu um erro
// try...finally
try{
console.log("executando bloco try...")
}finally{
console.log("declaração final")
}
// SAÍDA:
// executando bloco try...
// declaração final
// try...catch...finally
try{
console.log("executando bloco try...")
console.log(missingVar)
}catch(errorVar){
console.log("ocorreu um erro",errorVar)
}finally{
console.log("declaração final")
}
// SAÍDA:
// executando bloco try...
// ocorreu um erro
// declaração final
O bloco catch possui um identificador de erro que pode ser usado para acessar o erro gerado. Você pode acessá-lo como um todo (por exemplo, errorVar) ou usar suas propriedades individualmente:
errorVar.name– Especifica o tipo de erroerrorVar.message– Fornece uma descrição do erro legível para humanos
O trecho de código abaixo usa desestruturação para acessar o erro gerado:
try {
console.log(missingVar)
} catch ({name, message}) {
console.log("nome: ", name)
console.log("mensagem: ", message)
}
// SAÍDA:
// nome: ReferenceError
// mensagem: missingVar não está definida
Lançando erros personalizados
Às vezes, erros embutidos como TypeError não capturam completamente o que deu errado. Lançar erros personalizados permite fornecer mensagens de erro mais claras e incluir informações adicionais para depuração.
Para criar um erro personalizado, você estende a classe Error, define um construtor que define uma mensagem de erro significativa e atribui um nome personalizado. Você pode opcionalmente incluir informações adicionais de depuração e capturar o rastreamento de pilha original para depuração no desenvolvimento:
class OperationError extends Error {
/**
* Erro personalizado para lidar com falhas de operação.
* @param {string} resource - O recurso envolvido no erro.
* @param {string} action - A ação que falhou.
*/
constructor(resource, action) {
// Construa uma mensagem de erro significativa
super(`Falha ao ${action} ${resource}. Verifique o recurso e tente novamente.`);
// Preserve o rastreamento de pilha original (opcional, útil para depuração)
if (Error.captureStackTrace) {
Error.captureStackTrace(this, OperationError);
}
this.name = "OperationError";
// Informações de depuração personalizadas
this.resource = resource;
this.action = action;
}
}
No trecho de código abaixo, o erro personalizado é lançado no bloco try para simular uma chamada de função que pode encontrar esse tipo específico de erro. O objeto de erro inclui o rastreamento de pilha e propriedades adicionais de erro:
try {
// simular uma operação que pode lançar uma exceção
throw new OperationError("arquivo", "ler");
} catch (error) {
console.error(`${error.name}: ${error.message}`);
console.log(`informações adicionais: o recurso era um ${error.resource} e a ação era ${error.action}`)
console.log(error)
}
// SAÍDA:
// OperationError: Falha ao ler o arquivo. Verifique o recurso e tente novamente.
// informações adicionais: o recurso era um arquivo e a ação era ler
// OperationError: Falha ao ler o arquivo. Verifique o recurso e tente novamente.
// at Object.< anonymous > (/Users/walobwa / Desktop /project / test.js: 25: 11)
// at Module._compile(node: internal / modules / cjs / loader: 1376: 14)
// at Module._extensions..js(node: internal / modules / cjs / loader: 1435: 10)
// at Module.load(node: internal / modules / cjs / loader: 1207: 32)
// at Module._load(node: internal / modules / cjs / loader: 1023: 12)
// at Function.executeUserEntryPoint[as runMain](node: internal/modules/run_main: 135: 12)
// at node: internal / main / run_main_module: 28: 49 {
// resource: 'arquivo',
// action: 'ler'
// }
Blocos catch condicionais
Blocos catch condicionais usam a instrução if...else para lidar com erros específicos, permitindo que os inesperados sejam propagados.
Conhecer os diferentes tipos de erros que podem ser lançados ao executar o código ajuda a lidar com eles adequadamente. Usando instanceof, podemos capturar erros específicos como OperationError e fornecer uma mensagem significativa para o erro:
try {
// simular uma operação que pode lançar uma exceção
throw new OperationError("arquivo", "ler");
} catch (error) {
if (error instanceof OperationError) {
// lidar com erro esperado
console.error("Erro de Operação encontrado:", error.message);
} else {
// registrar erro inesperado
console.error("Erro inesperado encontrado:", error.message);
}
}
// SAÍDA:
// Erro de Operação encontrado: Falha ao ler o arquivo. Verifique o recurso e tente novamente.
No trecho de código acima, registramos qualquer outro erro na instrução else. Uma boa prática seria relançar erros não explicitamente tratados no bloco try...catch.
Relançando erros
Relançar erros garante que eles sejam propagados para cima na pilha de chamadas para tratamento. Isso evita falhas silenciosas e mantém o rastreamento de pilha.
No trecho de código abaixo, capturamos o erro esperado, OperationError, silenciamos e, em seguida, adiamos o tratamento de outros erros relançando-os. A função de nível superior agora lidará com o erro relançado:
try {
throw new TypeError("X não é uma função");
} catch (error) {
if (error instanceof OperationError) {
console.error("Erro de Operação encontrado:", error.message);
} else {
throw error; // relançar o erro inalterado
}
}
Bloco try…catch aninhado
Um bloco try...catch aninhado é usado quando uma operação dentro de um bloco try requer tratamento de erro separado. Ele ajuda a gerenciar várias falhas independentes, garantindo que uma falha não interrompa todo o fluxo de execução.
Erros no bloco interno são capturados e tratados localmente enquanto o bloco externo gerencia erros não tratados ou propagados. Se o erro gerado for tratado no bloco interno try..catch, o bloco catch externo não é executado:
try {
try {
throw new OperationError("arquivo", "ler");
} catch (e) {
if (e instanceof OperationError) {
console.error("Erro de Operação encontrado:", e.message);
} else {
throw e; // relançar o erro inalterado
}
} finally {
console.log("bloco finalmente interno");
}
} catch (err) {
console.error("registro de erro externo", err.message);
}
// SAÍDA:
// Erro de Operação encontrado: Falha ao ler o arquivo. Verifique o recurso e tente novamente.
// bloco finalmente interno
Se um erro não for tratado ou for relançado no bloco interno, o bloco try...catch externo o captura. O bloco finally aninhado é executado antes do bloco catch ou finally externo, garantindo a limpeza em cada nível:
try {
try {
throw new TypeError("arquivo");
} catch (e) {
if(e instanceof OperationError) {
console.error("Erro de Operação encontrado:", e.message);
} else {
throw e; // relançar o erro inalterado
}
} finally {
console.log("bloco finalmente interno");
}
} catch (err) {
console.error("registro de erro externo", err.message);
}
// SAÍDA:
// bloco finalmente interno
// registro de erro externo arquivo
Lidando com erros assíncronos
try...catch funciona com código síncrono. Quando um erro ocorre dentro de uma função assíncrona, o bloco try...catch conclui a execução antes que o erro ocorra, deixando-o não tratado.
Operações assíncronas requerem tratamento de erro adequado para evitar rejeições não tratadas e falhas inesperadas. Usar try...catch com async/await ajuda a evitar que rejeições não tratadas passem despercebidas.
async/await garante que o bloco try…catch espere o resultado da operação assíncrona antes de prosseguir:
async function openFile(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new OperationError("arquivo", "abrir"); // Reutilizando OperationError para lidar com erros de abertura de arquivo
}
return await response.json();
} catch (error) {
console.error(`Falha ao buscar arquivo: ${error.message}`);
// Relançar ou lidar de forma graciosa
throw error; // Propagar o erro para cima
}
}
No exemplo acima, a função openFile é assíncrona. O resultado da operação fetch é aguardado. Se um erro for lançado, ele é registrado e propagado para o bloco try...catch externo onde é tratado:
try {
const data = await openFile("data.json");
console.log(data);
} catch (error) {
console.error(`Falha ao abrir arquivo: ${error.message}`);
}
Usando finally para limpeza
O bloco finally em uma instrução try...catch é usado para executar código que deve ser executado independentemente de um erro ocorrer. Isso é útil para operações de limpeza, como fechar arquivos, liberar recursos ou redefinir estados:
try {
// operação que abre arquivo e lança erro de operação
throw new OperationError("arquivo", "ler");
} catch (error) {
if(error instanceof OperationError) {
console.error(`Erro de operação: ${error.message}`);
} else {
throw error;
}
} finally {
closeFile(file); // Garante que o arquivo seja fechado mesmo que ocorra um erro
}
Conclusão
Este tutorial explorou o tratamento de erros em JavaScript usando o bloco try...catch. Abordamos sua sintaxe básica, lançamento de erros personalizados, relançamento de erros e uso de blocos aninhados. Também discutimos o tratamento de erros assíncronos com try...catch e async/await, bem como o uso do bloco finally para limpeza de código.
Ao usar efetivamente try...catch, os desenvolvedores podem construir aplicações mais robustas, prevenir falhas inesperadas e melhorar a depuração, garantindo uma melhor experiência do usuário.