1

Pitch: Construí o Interceptor HTTP Definitivo para Angular: 6 Padrões de Resiliência e RxJS na Prática

Se você desenvolve aplicações Angular complexas, como sistemas de dashboards dinâmicos com múltiplos widgets ou interfaces baseadas em nós para mapear regras de processos, você sabe que a rede é o ambiente mais hostil do frontend.

Requisições simultâneas disputando a mesma URL, conexões instáveis, lentidão no servidor e o temido erro 401 quebrando dezenas de chamadas paralelas. A abordagem clássica é criar um HttpInterceptor gigante, que rapidamente se torna um "God Object" impossível de manter.

Para resolver isso aplicando os princípios SOLID (focando fortemente no SRP - Princípio da Responsabilidade Única), desenvolvi o ngx-smart-interceptor. Vale ressaltar que este é um projeto experimental e em constante evolução. Estou aprendendo muito durante todo o processo de construção de uma biblioteca do zero, iterando e melhorando a arquitetura a cada novo desafio.

Em vez de processar regras, o interceptor principal atua apenas como um Orquestrador, delegando o trabalho pesado do RxJS para Handlers especialistas. Criei um Sandbox para validar a biblioteca sob estresse, e aqui estão os 6 pilares de resiliência que ela entrega com poucas linhas de configuração.


1. Deduplicação de Requisições (In-Flight Caching)

Em grids complexos, é comum que vários componentes peçam o mesmo dicionário de dados (ex: GET /api/status) ao mesmo tempo. O DeduplicationHandler entra em ação usando o operador shareReplay(1) do RxJS.

Se o seu código disparar 3 requisições simultâneas, apenas uma chamada real vai para a aba Network:

// No seu componente, mesmo se você forçar chamadas simultâneas...
ngOnInit() {
  forkJoin({
    widgetA: this.http.get('/api/config'),
    widgetB: this.http.get('/api/config'),
    widgetC: this.http.get('/api/config')
  }).subscribe(res => {
    // Todos os 3 recebem os dados ao mesmo tempo,
    // mas o servidor só recebeu 1 requisição!
    console.log(res);
  });
}

2. Padrão Circuit Breaker

Se a sua API de inteligência de negócios cair (Erro 500), o frontend não deve metralhar o servidor com retries cegos.

O CircuitBreakerHandler vigia falhas consecutivas. Ao atingir o limite (ex: 3 falhas), ele "desarma" o circuito. Novas requisições são bloqueadas diretamente no navegador (sem ir à rede) e um erro local é retornado instantaneamente, dando tempo para o servidor respirar.


3. Fila Offline (Offline Queue)

Imagine o usuário montando um diagrama complexo e clicando em "Salvar" (POST) justo quando o Wi-Fi cai.

Com a enableOfflineQueue ativa, o interceptor captura a falha de rede. Ele guarda o POST na memória e, assim que o navegador emite o evento online, ele reprocessa a fila silenciosamente em background. Seu usuário nunca perde dados.


4. Adaptive Loading (Carregamento Adaptativo)

O interceptor possui um profiler que percebe quando a conexão está estrangulada (alta latência).

Ele injeta automaticamente o cabeçalho X-Adaptive-Network: slow na requisição. No seu backend (seja Node, C# ou Java), você pode ler esse header e retornar um payload menor para salvar a experiência do usuário:

// Exemplo no Backend (Express.js) consumindo o cabeçalho
app.get('/api/dashboard', (req, res) => {
  const isSlowNetwork = req.headers['x-adaptive-network'] === 'slow';
  
  if (isSlowNetwork) {
    return res.json(getLightweightData()); // Sem imagens pesadas
  }
  return res.json(getFullData());
});

5. Observabilidade & Profiler

Se uma chamada de API demorar mais de 3 segundos, o interceptor dispara um alerta de degradação (Slow Request Warning) diretamente no console ou para o seu serviço de monitoramento (como Sentry).


6. Global Hooks e Erros Normalizados

O terror do Angular é lidar com o objeto nativo HttpErrorResponse espalhado pelos componentes. O Orquestrador normaliza os erros e permite a injeção de Global Hooks para lidar com situações críticas (como o erro 401 Unauthorized) em um único lugar.

Veja como é fácil configurar a renovação de Token globalmente:

// app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(withInterceptors([smartInterceptor])),
    provideSmartInterceptor({
      generateCorrelationIds: true,
      globalHooks: {
        // Intercepta TODOS os 401s da aplicação
        onUnauthorized: (err, req) => {
          console.warn('Sessão expirada. Redirecionando ou renovando token...');
          const authService = inject(AuthService);
          authService.logout();
        }
      }
    })
  ]
};

Como fica o código no dia a dia?

A beleza de usar um interceptor inteligente é que o código dos seus componentes fica extremamente limpo.

Você não precisa escrever lógicas complexas de tentativa (retry) ou tratar mensagens de rede obscuras. O interceptor injeta uma userFriendlyMessage e um correlationId para rastreabilidade:

// dashboard.component.ts
salvarFluxo() {
  this.http.post('/api/process', this.payload).pipe(
    catchError((error) => {
      // O interceptor já tratou bloqueios de Circuit Breaker ou falhas de rede.
      // O erro chega limpo e padronizado para a interface:
      
      this.toastService.showError(error.userFriendlyMessage);
      console.error(`Falha rastreável: ${error.correlationId}`);
      
      return EMPTY;
    })
  ).subscribe(() => {
    this.toastService.showSuccess('Fluxo salvo com sucesso!');
  });
}

Conclusão

Construir bibliotecas robustas é sobre dominar as ferramentas do ecossistema e aplicar padrões de Engenharia de Software. O ngx-smart-interceptor prova que é possível transformar a caótica camada de rede do frontend em um pipeline previsível, resiliente e altamente testável.

Convido você a testar a biblioteca, ver a documentação completa gerada via Compodoc e analisar a arquitetura do código fonte (que conta com uma esteira automatizada de CI/CD completa).

GitHub: https://github.com/ErickG123/ngx-smart-interceptor
NPM: npm install ngx-smart-interceptor

Se a biblioteca for útil para os seus projetos, considere deixar uma ⭐ no repositório! Toda contribuição e Pull Request da comunidade é super bem-vinda.

Carregando publicação patrocinada...