advanced async patterns
Módulo 2: JavaScript Assíncrono
Aula 2
1
Tratamento Avançado de Erros em Código Assíncrono
Aprenda padrões sofisticados de tratamento de erros para JavaScript assíncrono
Tratamento Avançado de Erros em Código Assíncrono
O tratamento adequado de erros é crucial para aplicações assíncronas robustas. Este guia cobre padrões avançados e melhores práticas.
Estratégias de Tratamento de Erros
1. Try-Catch com Async/Await
async function chamadaDeApiRobusta() {
try {
const resposta = await fetch('/api/dados');
if (!resposta.ok) {
throw new Error(`HTTP ${resposta.status}: ${resposta.statusText}`);
}
const dados = await resposta.json();
return dados;
} catch (erro) {
if (erro instanceof TypeError) {
// Erro de rede
console.error('Erro de rede:', erro.message);
} else if (erro.message.includes('HTTP')) {
// Erro HTTP
console.error('Erro de API:', erro.message);
} else {
// Erro desconhecido
console.error('Erro inesperado:', erro);
}
throw erro; // Re-lança para o chamador tratar
}
}
2. Padrões de Recuperação de Erros
Tentativa com Backoff Exponencial
async function tentarComBackoff(fn, maxTentativas = 3, atrasoBase = 1000) {
for (let tentativa = 1; tentativa <= maxTentativas; tentativa++) {
try {
return await fn();
} catch (erro) {
if (tentativa === maxTentativas) {
throw erro;
}
const atraso = atrasoBase * Math.pow(2, tentativa - 1);
console.log(`Tentativa ${tentativa} falhou, tentando novamente em ${atraso}ms...`);
await new Promise(resolve => setTimeout(resolve, atraso));
}
}
}
// Uso
const resultado = await tentarComBackoff(() => fetch('/api/endpoint-instavel'), 3, 1000);
Mecanismos de Fallback
async function buscarComFallback(urlPrimaria, urlFallback) {
try {
const resposta = await fetch(urlPrimaria);
if (!resposta.ok) throw new Error('Serviço primário falhou');
return await resposta.json();
} catch (erroPrimario) {
console.warn('Serviço primário falhou, tentando fallback:', erroPrimario.message);
try {
const resposta = await fetch(urlFallback);
if (!resposta.ok) throw new Error('Serviço de fallback falhou');
return await resposta.json();
} catch (erroFallback) {
throw new Error(`Ambos os serviços falharam: ${erroPrimario.message}, ${erroFallback.message}`);
}
}
}
3. Padrão Circuit Breaker
class CircuitBreaker {
constructor(limite = 5, tempoDeEspera = 60000) {
this.limite = limite;
this.tempoDeEspera = tempoDeEspera;
this.contadorDeFalhas = 0;
this.estado = 'FECHADO'; // FECHADO, ABERTO, SEMIABERTO
this.proximaTentativa = Date.now();
}
async chamar(fn) {
if (this.estado === 'ABERTO') {
if (Date.now() < this.proximaTentativa) {
throw new Error('Circuit breaker está ABERTO');
}
this.estado = 'SEMIABERTO';
}
try {
const resultado = await fn();
this.aoSucesso();
return resultado;
} catch (erro) {
this.aoFalhar();
throw erro;
}
}
aoSucesso() {
this.contadorDeFalhas = 0;
this.estado = 'FECHADO';
}
aoFalhar() {
this.contadorDeFalhas++;
if (this.contadorDeFalhas >= this.limite) {
this.estado = 'ABERTO';
this.proximaTentativa = Date.now() + this.tempoDeEspera;
}
}
}
// Uso
const breaker = new CircuitBreaker(3, 30000);
async function chamarServico() {
return breaker.chamar(() => fetch('/api/servico'));
}
Agregação de Erros
Coletando Múltiplos Erros
async function processarItensComErros(itens) {
const resultados = [];
const erros = [];
for (const item of itens) {
try {
const resultado = await processarItem(item);
resultados.push(resultado);
} catch (erro) {
erros.push({ item, erro });
}
}
if (erros.length > 0) {
console.warn(`${erros.length} itens falharam ao processar:`, erros);
}
return { resultados, erros };
}
Tratamento de Sucesso Parcial
async function processamentoEmLote(itens, opcoes = {}) {
const { falhaRapida = false, maxConcorrencia = 3 } = opcoes;
const resultados = [];
const erros = [];
// Processar em lotes
for (let i = 0; i < itens.length; i += maxConcorrencia) {
const lote = itens.slice(i, i + maxConcorrencia);
const promessasDoLote = lote.map(async (item, indice) => {
try {
const resultado = await processarItem(item);
return { sucesso: true, resultado, item };
} catch (erro) {
if (falhaRapida) throw erro;
return { sucesso: false, erro, item };
}
});
const resultadosDoLote = await Promise.allSettled(promessasDoLote);
resultadosDoLote.forEach(resultado => {
if (resultado.status === 'fulfilled') {
if (resultado.value.sucesso) {
resultados.push(resultado.value.resultado);
} else {
erros.push(resultado.value);
}
} else {
erros.push({ erro: resultado.reason });
}
});
}
return { resultados, erros, totalProcessado: itens.length };
}
2
Recursos de JavaScript Assíncrono
Recursos adicionais para dominar o JavaScript assíncrono
Reference
Recursos de JavaScript Assíncrono
Aqui estão alguns excelentes recursos para aprofundar sua compreensão do JavaScript assíncrono:
Documentação Oficial
Tópicos Avançados
- Ferramentas de visualização do Event Loop
- Profiling de performance para código assíncrono
- Padrões avançados de promises
- Geradores e iteradores assíncronos
Livros e Artigos
- "Você Não Sabe JS: Async & Performance" por Kyle Simpson
- "JavaScript Eficaz" por David Herman
- "JavaScript: As Partes Boas" por Douglas Crockford
Ferramentas e Bibliotecas
- Depuração assíncrona no Chrome DevTools
- Biblioteca de promises Bluebird
- RxJS para programação reativa
- p-limit para controle de concorrência
Clique no link acima para explorar a documentação abrangente da MDN sobre promises em JavaScript!
2 content items