CodeToLive

Angular HTTP Client

Angular provides HttpClient for communicating with backend services over HTTP. It offers a simplified API for HTTP requests with built-in support for interceptors and RxJS.

Setting Up HttpClient

First, import HttpClientModule in your app module:


// app.module.ts
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  imports: [
    HttpClientModule
  ]
})
export class AppModule { }
                

Basic HTTP Requests

Inject HttpClient in your service or component:


import { HttpClient } from '@angular/common/http';

constructor(private http: HttpClient) { }

// GET request
getProducts() {
  return this.http.get('https://api.example.com/products');
}

// GET with parameters
getProduct(id: number) {
  return this.http.get(`https://api.example.com/products/${id}`);
}

// POST request
addProduct(product: Product) {
  return this.http.post('https://api.example.com/products', product);
}

// PUT request
updateProduct(product: Product) {
  return this.http.put(`https://api.example.com/products/${product.id}`, product);
}

// DELETE request
deleteProduct(id: number) {
  return this.http.delete(`https://api.example.com/products/${id}`);
}
                

Typed Responses

Specify response types for better type safety:


interface Product {
  id: number;
  name: string;
  price: number;
}

getProducts(): Observable<Product[]> {
  return this.http.get<Product[]>('https://api.example.com/products');
}
                

Error Handling

Handle errors using RxJS catchError:


import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';

getProducts() {
  return this.http.get<Product[]>('https://api.example.com/products')
    .pipe(
      catchError(error => {
        console.error('Error:', error);
        return throwError('Something went wrong');
      })
    );
}
                

HTTP Headers

Add headers to your requests:


import { HttpHeaders } from '@angular/common/http';

const headers = new HttpHeaders()
  .set('Content-Type', 'application/json')
  .set('Authorization', 'Bearer token123');

getProducts() {
  return this.http.get<Product[]>('https://api.example.com/products', { headers });
}
                

Request Parameters

Add query parameters to GET requests:


import { HttpParams } from '@angular/common/http';

searchProducts(term: string) {
  const params = new HttpParams()
    .set('q', term)
    .set('page', '1');
    
  return this.http.get<Product[]>('https://api.example.com/products', { params });
}
                

Progress Events

Track upload/download progress:


uploadFile(file: File) {
  const formData = new FormData();
  formData.append('file', file);
  
  return this.http.post('https://api.example.com/upload', formData, {
    reportProgress: true,
    observe: 'events'
  });
}
                

Interceptors

Create HTTP interceptors for cross-cutting concerns:


// auth.interceptor.ts
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const authReq = req.clone({
      headers: req.headers.set('Authorization', 'Bearer token123')
    });
    
    return next.handle(authReq);
  }
}

// Register in app module
@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
  ]
})
export class AppModule { }
                

Retry Failed Requests

Automatically retry failed requests:


import { retry } from 'rxjs/operators';

getProducts() {
  return this.http.get<Product[]>('https://api.example.com/products')
    .pipe(
      retry(3) // Retry up to 3 times before failing
    );
}
                

Debouncing Search Requests

Optimize search requests with debounce:


import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';

private searchTerms = new Subject<string>();

search(term: string): void {
  this.searchTerms.next(term);
}

ngOnInit() {
  this.products$ = this.searchTerms.pipe(
    debounceTime(300),  // wait 300ms after each keystroke
    distinctUntilChanged(),  // ignore if same as previous term
    switchMap(term => term  // switch to new observable each time term changes
      ? this.productService.searchProducts(term)
      : of<Product[]>([]))
  );
}
                

Caching Responses

Cache HTTP responses to avoid duplicate requests:


private cache = new Map<string, any>();

getProducts(): Observable<Product[]> {
  const url = 'https://api.example.com/products';
  
  if (this.cache.has(url)) {
    return of(this.cache.get(url));
  }
  
  return this.http.get<Product[]>(url).pipe(
    tap(response => this.cache.set(url, response))
  );
}
                
Next: State Management