Tratamento Avançado de Erros em JavaScript: do try/catch aos Interceptadores Globais
\n\nO tratamento de erros não é apenas "envolver o código em try/catch". Em aplicações reais de produção em Node.js, o gerenciamento adequado de exceções permite evitar quedas do servidor, registrar problemas corretamente e fornecer mensagens compreensíveis ao usuário. Neste artigo, abordaremos técnicas avançadas de tratamento de erros em JavaScript que vão além da sintaxe básica.
\n\n1. Mergulho Profundo em try/catch e finally
\n\nA construção clássica try...catch...finally continua sendo a base do tratamento síncrono. No entanto, em um nível avançado, é importante entender as nuances do seu funcionamento.
function riskyOperation(value) {\n if (typeof value !== 'number') {\n throw new TypeError('Argument must be a number');\n }\n if (value < 0) {\n throw new RangeError('Value cannot be negative');\n }\n return Math.sqrt(value);\n}\n\ntry {\n const result = riskyOperation(-4);\n console.log('Result:', result);\n} catch (error) {\n if (error instanceof TypeError) {\n console.error('Type Error:', error.message);\n } else if (error instanceof RangeError) {\n console.error('Range Error:', error.message);\n } else {\n console.error('Unknown error:', error);\n }\n} finally {\n console.log('Cleanup: always executed');\n}\n\nPontos-chave:
\n- \n
- O bloco
finallyé executado sempre, mesmo se houverreturnemtryoucatch. \n - Use classes de erro integradas (
TypeError,RangeError,SyntaxError) para identificação precisa. \n - Não capture erros que você não pode tratar — deixe-os propagar para cima. \n
2. Classes de Erro Personalizadas e Extensão de Error
\n\nPara projetos grandes, os tipos de erro padrão não são suficientes. Criar suas próprias classes permite adicionar metadados (status HTTP, código de erro, contexto) e simplifica a filtragem.
\n\nclass AppError extends Error {\n constructor(message, statusCode, code) {\n super(message);\n this.name = 'AppError';\n this.statusCode = statusCode;\n this.code = code;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nclass ValidationError extends AppError {\n constructor(message, field) {\n super(message, 400, 'VALIDATION_ERROR');\n this.field = field;\n }\n}\n\nclass DatabaseError extends AppError {\n constructor(message, query) {\n super(message, 500, 'DB_ERROR');\n this.query = query;\n }\n}\n\n// Uso\ntry {\n throw new ValidationError('Email is required', 'email');\n} catch (error) {\n if (error instanceof ValidationError) {\n console.log(`Field: ${error.field}, Status: ${error.statusCode}`);\n }\n}\n\nPor que isso é importante: erros personalizados permitem tratar centralizadamente diferentes cenários (por exemplo, em middleware Express.js) e retornar JSON estruturado ao cliente.
\n\n3. Tratamento de Erros em Código Assíncrono: async/await e Promise
\n\nEm Node.js, a maior parte do código é assíncrona. Erros em Promise e async/await exigem uma abordagem especial.
3.1. Tratamento de Promise
\n\nfunction fetchUserData(userId) {\n return new Promise((resolve, reject) => {\n if (userId <= 0) {\n reject(new RangeError('Invalid user ID'));\n }\n // simulação de consulta ao BD\n setTimeout(() => resolve({ id: userId, name: 'Alice' }), 100);\n });\n}\n\nfetchUserData(-1)\n .then(user => console.log(user))\n .catch(error => {\n console.error('Promise rejected:', error.message);\n })\n .finally(() => console.log('Cleanup after promise'));\n\n3.2. Tratamento de async/await
\n\nasync function getUserProfile(userId) {\n try {\n const user = await fetchUserData(userId);\n const posts = await fetchUserPosts(user.id