Angular HTTP Client and RxJS

Angular HTTP Client and RxJS

Angular's HttpClient returns RxJS Observables, making it easy to handle async data with operators like map, catchError, switchMap, and forkJoin.

Setup HttpClient

// app.config.ts
import { provideHttpClient, withInterceptors } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(withInterceptors([authInterceptor])),
  ],
};

Common RxJS Operators

import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, forkJoin, throwError } from 'rxjs';
import { map, catchError, switchMap, tap, retry } from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class DataService {
  private http = inject(HttpClient);

  // Transform response
  getUserNames(): Observable<string[]> {
    return this.http.get<User[]>('/api/users').pipe(
      map(users => users.map(u => u.name)),
      retry(2),
      catchError(err => {
        console.error(err);
        return throwError(() => new Error('Failed to load users'));
      })
    );
  }

  // Chain requests
  getUserWithPosts(userId: number): Observable<{ user: User; posts: Post[] }> {
    return this.http.get<User>(`/api/users/${userId}`).pipe(
      switchMap(user =>
        this.http.get<Post[]>(`/api/users/${userId}/posts`).pipe(
          map(posts => ({ user, posts }))
        )
      )
    );
  }

  // Parallel requests
  getDashboardData(): Observable<[User[], Post[], Comment[]]> {
    return forkJoin([
      this.http.get<User[]>('/api/users'),
      this.http.get<Post[]>('/api/posts'),
      this.http.get<Comment[]>('/api/comments'),
    ]);
  }
}

HTTP Interceptor

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

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const token = inject(AuthService).getToken();
  if (token) {
    req = req.clone({ setHeaders: { Authorization: `Bearer ${token}` } });
  }
  return next(req);
};