Angular HttpClient e Interceptors em 2026: Tratamento de Requisições e Perguntas de Entrevista

Guia completo sobre HttpClient e interceptors no Angular em 2026. Arquitetura de requisições HTTP, tratamento de erros, autenticação e perguntas frequentes em entrevistas técnicas.

Angular HttpClient e Interceptors

O Angular permanece em 2026 como um dos frameworks frontend mais utilizados em ambientes corporativos, e o domínio do HttpClient representa uma habilidade essencial para qualquer desenvolvedor Angular. Este guia explora em profundidade o funcionamento do HttpClient, a arquitetura dos interceptors funcionais, e as perguntas mais frequentes em entrevistas técnicas.

Desde o Angular 15, os interceptors funcionais substituem progressivamente os interceptors baseados em classes. Este guia aborda ambas as abordagens, com foco nos padrões modernos recomendados em 2026.

Configuração do HttpClient no Angular 19

A configuração do HttpClient evoluiu consideravelmente com a adoção de standalone components. O método moderno utiliza provideHttpClient() na configuração da aplicação.

app.config.tstypescript
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient, withInterceptors, withFetch } from '@angular/common/http';
import { authInterceptor } from './interceptors/auth.interceptor';
import { errorInterceptor } from './interceptors/error.interceptor';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(
      withInterceptors([authInterceptor, errorInterceptor]),
      withFetch() // Uses fetch API instead of XMLHttpRequest
    )
  ]
};

A opção withFetch() permite utilizar a API Fetch nativa do navegador em vez do XMLHttpRequest, oferecendo melhor desempenho e uma integração mais fluida com os Service Workers.

Criação de um Serviço HTTP Tipado

Um serviço HTTP bem estruturado constitui a base de uma arquitetura Angular robusta. O uso de genéricos TypeScript garante a segurança de tipos em toda a aplicação.

services/api.service.tstypescript
import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../environments/environment';

export interface ApiResponse<T> {
  data: T;
  message: string;
  status: number;
}

export interface PaginatedResponse<T> {
  items: T[];
  total: number;
  page: number;
  pageSize: number;
}

@Injectable({ providedIn: 'root' })
export class ApiService {
  private http = inject(HttpClient);
  private baseUrl = environment.apiUrl;

  get<T>(endpoint: string, params?: Record<string, string>): Observable<ApiResponse<T>> {
    const httpParams = new HttpParams({ fromObject: params || {} });
    return this.http.get<ApiResponse<T>>(`${this.baseUrl}${endpoint}`, { params: httpParams });
  }

  post<T, R>(endpoint: string, body: T): Observable<ApiResponse<R>> {
    return this.http.post<ApiResponse<R>>(`${this.baseUrl}${endpoint}`, body);
  }

  put<T, R>(endpoint: string, body: T): Observable<ApiResponse<R>> {
    return this.http.put<ApiResponse<R>>(`${this.baseUrl}${endpoint}`, body);
  }

  delete<T>(endpoint: string): Observable<ApiResponse<T>> {
    return this.http.delete<ApiResponse<T>>(`${this.baseUrl}${endpoint}`);
  }

  uploadFile(endpoint: string, file: File): Observable<ApiResponse<{ url: string }>> {
    const formData = new FormData();
    formData.append('file', file);
    return this.http.post<ApiResponse<{ url: string }>>(`${this.baseUrl}${endpoint}`, formData);
  }
}

Interceptors Funcionais: A Abordagem Moderna

Os interceptors funcionais introduzidos no Angular 15 oferecem uma sintaxe mais concisa e melhor composabilidade. Eles se integram perfeitamente com a arquitetura standalone.

Interceptor de Autenticação

A adição automática do token de autenticação representa o caso de uso mais comum dos interceptors.

interceptors/auth.interceptor.tstypescript
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { AuthService } from '../services/auth.service';

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const authService = inject(AuthService);
  const token = authService.getAccessToken();

  if (token && !req.url.includes('/auth/')) {
    const clonedRequest = req.clone({
      setHeaders: {
        Authorization: `Bearer ${token}`
      }
    });
    return next(clonedRequest);
  }

  return next(req);
};

Interceptor de Tratamento de Erros

Um interceptor centralizado para o tratamento de erros simplifica consideravelmente o código dos componentes.

interceptors/error.interceptor.tstypescript
import { HttpInterceptorFn, HttpErrorResponse } from '@angular/common/http';
import { inject } from '@angular/core';
import { Router } from '@angular/router';
import { catchError, throwError } from 'rxjs';
import { NotificationService } from '../services/notification.service';

export const errorInterceptor: HttpInterceptorFn = (req, next) => {
  const router = inject(Router);
  const notifications = inject(NotificationService);

  return next(req).pipe(
    catchError((error: HttpErrorResponse) => {
      switch (error.status) {
        case 401:
          router.navigate(['/login']);
          break;
        case 403:
          notifications.error('Access denied');
          break;
        case 404:
          notifications.error('Resource not found');
          break;
        case 500:
          notifications.error('Server error. Please try again later.');
          break;
        default:
          notifications.error(error.message || 'An error occurred');
      }
      return throwError(() => error);
    })
  );
};

Interceptor de Retry com Backoff Exponencial

O tratamento de falhas de rede transitórias requer uma estratégia de retry inteligente.

interceptors/retry.interceptor.tstypescript
import { HttpInterceptorFn } from '@angular/common/http';
import { retry, timer } from 'rxjs';

export const retryInterceptor: HttpInterceptorFn = (req, next) => {
  const maxRetries = 3;
  const delayMs = 1000;

  return next(req).pipe(
    retry({
      count: maxRetries,
      delay: (error, retryCount) => {
        if (error.status >= 400 && error.status < 500) {
          throw error; // Don't retry client errors
        }
        const backoffDelay = delayMs * Math.pow(2, retryCount - 1);
        console.log(`Retry attempt ${retryCount} after ${backoffDelay}ms`);
        return timer(backoffDelay);
      }
    })
  );
};

Gerenciamento de Cache com Interceptors

A implementação de um cache HTTP no nível do interceptor permite otimizar o desempenho sem modificar os serviços existentes.

interceptors/cache.interceptor.tstypescript
import { HttpInterceptorFn, HttpResponse } from '@angular/common/http';
import { of, tap } from 'rxjs';

const cache = new Map<string, { response: HttpResponse<unknown>; timestamp: number }>();
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes

export const cacheInterceptor: HttpInterceptorFn = (req, next) => {
  if (req.method !== 'GET') {
    return next(req);
  }

  const cacheKey = req.urlWithParams;
  const cached = cache.get(cacheKey);

  if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
    return of(cached.response.clone());
  }

  return next(req).pipe(
    tap((event) => {
      if (event instanceof HttpResponse) {
        cache.set(cacheKey, { response: event.clone(), timestamp: Date.now() });
      }
    })
  );
};

Interceptor de Loading Global

A exibição automática de um indicador de carregamento melhora a experiência do usuário.

interceptors/loading.interceptor.tstypescript
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { finalize } from 'rxjs';
import { LoadingService } from '../services/loading.service';

export const loadingInterceptor: HttpInterceptorFn = (req, next) => {
  const loadingService = inject(LoadingService);
  
  if (req.headers.has('X-Skip-Loading')) {
    return next(req);
  }

  loadingService.show();

  return next(req).pipe(
    finalize(() => loadingService.hide())
  );
};

Padrões Avançados: Refresh Token Automático

O gerenciamento automático do refresh token representa um padrão essencial para aplicações seguras.

interceptors/token-refresh.interceptor.tstypescript
import { HttpInterceptorFn, HttpErrorResponse } from '@angular/common/http';
import { inject } from '@angular/core';
import { BehaviorSubject, throwError } from 'rxjs';
import { catchError, filter, switchMap, take } from 'rxjs/operators';
import { AuthService } from '../services/auth.service';

let isRefreshing = false;
const refreshTokenSubject = new BehaviorSubject<string | null>(null);

export const tokenRefreshInterceptor: HttpInterceptorFn = (req, next) => {
  const authService = inject(AuthService);

  return next(req).pipe(
    catchError((error: HttpErrorResponse) => {
      if (error.status !== 401 || req.url.includes('/auth/refresh')) {
        return throwError(() => error);
      }

      if (isRefreshing) {
        return refreshTokenSubject.pipe(
          filter((token) => token !== null),
          take(1),
          switchMap((token) => {
            const cloned = req.clone({
              setHeaders: { Authorization: `Bearer ${token}` }
            });
            return next(cloned);
          })
        );
      }

      isRefreshing = true;
      refreshTokenSubject.next(null);

      return authService.refreshToken().pipe(
        switchMap((response) => {
          isRefreshing = false;
          refreshTokenSubject.next(response.accessToken);
          const cloned = req.clone({
            setHeaders: { Authorization: `Bearer ${response.accessToken}` }
          });
          return next(cloned);
        }),
        catchError((refreshError) => {
          isRefreshing = false;
          authService.logout();
          return throwError(() => refreshError);
        })
      );
    })
  );
};

Pronto para mandar bem nas entrevistas de Angular?

Pratique com nossos simuladores interativos, flashcards e testes tecnicos.

Perguntas Frequentes em Entrevistas

As seguintes perguntas aparecem regularmente durante as entrevistas técnicas de Angular.

Qual é a diferença entre HttpClient e a API Fetch nativa?

O HttpClient oferece várias vantagens sobre a API Fetch: integração nativa com RxJS, sistema de interceptors, tipagem forte com TypeScript, e tratamento automático de serialização JSON. A API Fetch é mais leve, mas requer mais código boilerplate.

Como funciona a ordem de execução dos interceptors?

Os interceptors são executados na ordem de sua declaração para as requisições de saída, e na ordem inversa para as respostas de entrada. Essa arquitetura em "cebola" permite encadear as transformações de forma previsível.

Como cancelar uma requisição HTTP em andamento?

O cancelamento é realizado através da desinscrição do Observable retornado pelo HttpClient. O uso do operador takeUntil com um Subject permite gerenciar corretamente o cancelamento durante a destruição de um componente.

typescript
// Example: Cancelling requests on component destroy
import { Component, OnDestroy } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';

@Component({ /* ... */ })
export class SearchComponent implements OnDestroy {
  private destroy$ = new Subject<void>();

  search(term: string) {
    this.apiService.search(term)
      .pipe(takeUntil(this.destroy$))
      .subscribe(results => this.results = results);
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

Quando usar HttpParams vs um objeto simples?

HttpParams garante a codificação correta dos parâmetros de URL e suporta valores múltiplos para uma mesma chave. Um objeto simples é adequado para casos simples, mas HttpParams é recomendado para requisições complexas.

Como testar um serviço que utiliza HttpClient?

O Angular fornece HttpTestingController para simular as requisições HTTP em testes unitários. Essa abordagem permite verificar as URLs chamadas, os headers enviados, e simular diferentes respostas.

typescript
// Example: Testing HTTP service
import { TestBed } from '@angular/core/testing';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { provideHttpClient } from '@angular/common/http';

describe('ApiService', () => {
  let service: ApiService;
  let httpMock: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        provideHttpClient(),
        provideHttpClientTesting()
      ]
    });
    service = TestBed.inject(ApiService);
    httpMock = TestBed.inject(HttpTestingController);
  });

  it('should fetch users', () => {
    const mockUsers = [{ id: 1, name: 'John' }];

    service.get<User[]>('/users').subscribe(response => {
      expect(response.data).toEqual(mockUsers);
    });

    const req = httpMock.expectOne('/api/users');
    expect(req.request.method).toBe('GET');
    req.flush({ data: mockUsers, message: 'OK', status: 200 });
  });

  afterEach(() => {
    httpMock.verify();
  });
});

Boas Práticas em 2026

Várias recomendações emergem para um uso otimizado do HttpClient em produção.

A centralização das chamadas HTTP em serviços dedicados facilita a manutenção e os testes. O uso sistemático de interceptors para preocupações transversais (autenticação, logging, cache) evita a duplicação de código.

A tipagem estrita de todas as respostas da API com interfaces TypeScript permite detectar erros em tempo de compilação. A adoção de interceptors funcionais simplifica a configuração e melhora o desempenho graças ao tree-shaking.

O tratamento explícito de erros em cada nível (interceptor global para erros comuns, tratamento específico em componentes para casos particulares) garante uma experiência de usuário consistente.

Conclusão

HttpClient e os interceptors constituem a base da comunicação HTTP em aplicações Angular. O domínio desses conceitos, desde os padrões básicos até técnicas avançadas como o refresh token automático, representa uma competência chave avaliada em entrevistas técnicas. A adoção de interceptors funcionais e as boas práticas apresentadas neste guia permite construir aplicações robustas e de fácil manutenção.

Desafio do dia

Você saberia encontrar o bug em Angular?

Um trecho real, um bug escondido, uma tentativa por dia. Sem conta para testar.

Anthony Fillion-Maillet

Escrito por

Anthony Fillion-Maillet

Fundador da SharpSkill

Desenvolvedor fullstack há mais de 10 anos. Dirige a SharpSkill e responde por tudo o que é publicado aqui.

Atualizado em 22 de agosto de 2026

Tags

#angular
#httpclient
#interceptors
#http
#typescript

Compartilhar

Artigos relacionados