HTTP Client & Observables
HTTP Client Configuration
import { provideHttpClient } from '@angular/common/http';
// main.ts
bootstrapApplication(AppComponent, {
providers: [provideHttpClient()]
});
Basic HTTP Requests
import { HttpClient } from '@angular/common/http';
import { inject } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class UserService {
http = inject(HttpClient);
apiUrl = 'https://api.example.com/users';
// GET
getUsers() {
return this.http.get<User[]>(this.apiUrl);
}
// GET by ID
getUser(id: number) {
return this.http.get<User>(`${this.apiUrl}/${id}`);
}
// POST
createUser(user: User) {
return this.http.post<User>(this.apiUrl, user);
}
// PUT
updateUser(id: number, user: User) {
return this.http.put<User>(`${this.apiUrl}/${id}`, user);
}
// PATCH
patchUser(id: number, changes: Partial<User>) {
return this.http.patch<User>(`${this.apiUrl}/${id}`, changes);
}
// DELETE
deleteUser(id: number) {
return this.http.delete(`${this.apiUrl}/${id}`);
}
}
Using in Component
@Component({
selector: 'app-user-list',
template: `
<div *ngFor="let user of users$ | async">
{{ user.name }}
</div>
`
})
export class UserListComponent {
userService = inject(UserService);
users$ = this.userService.getUsers();
// Ou avec subscribe
users: User[] = [];
ngOnInit() {
this.userService.getUsers().subscribe({
next: (data) => this.users = data,
error: (err) => console.error(err),
complete: () => console.log('Complete')
});
}
}
HTTP Headers & Params
import { HttpHeaders, HttpParams } from '@angular/common/http';
// Headers
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
});
this.http.get(url, { headers });
// Query params
const params = new HttpParams()
.set('page', '1')
.set('limit', '10')
.set('sort', 'name');
this.http.get(url, { params });
// GET /api/users?page=1&limit=10&sort=name
// Ou avec la syntaxe objet
this.http.get(url, {
params: { page: '1', limit: '10' }
});
Interceptors
import { HttpInterceptorFn } from '@angular/common/http';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = localStorage.getItem('token');
if (token) {
req = req.clone({
setHeaders: { Authorization: `Bearer ${token}` }
});
}
return next(req);
};
// Fournir dans main.ts
provideHttpClient(
withInterceptors([authInterceptor])
);
Error Handling
import { catchError, throwError } from 'rxjs';
getUsers() {
return this.http.get<User[]>(this.apiUrl).pipe(
catchError(error => {
console.error('Error:', error);
return throwError(() => new Error('Failed to load users'));
})
);
}
// In component
this.userService.getUsers().subscribe({
next: data => this.users = data,
error: err => this.errorMessage = err.message
});
Retry & Timeout
import { retry, timeout } from 'rxjs/operators';
getUsers() {
return this.http.get<User[]>(this.apiUrl).pipe(
timeout(5000), // 5 seconds
retry(3), // Retry 3 times on failure
catchError(this.handleError)
);
}
Observable Operators
import { map, filter, tap } from 'rxjs/operators';
// Transform data
getActiveUsers() {
return this.http.get<User[]>(this.apiUrl).pipe(
map(users => users.filter(u => u.active)),
tap(users => console.log('Active users:', users))
);
}
// Chain requests
getUserWithPosts(userId: number) {
return this.http.get<User>(`/users/${userId}`).pipe(
switchMap(user =>
this.http.get<Post[]>(`/posts?userId=${userId}`).pipe(
map(posts => ({ user, posts }))
)
)
);
}
Combining Observables
import { forkJoin, combineLatest } from 'rxjs';
// Attendre que toutes les requêtes soient terminées
loadData() {
forkJoin({
users: this.http.get<User[]>('/users'),
posts: this.http.get<Post[]>('/posts'),
comments: this.http.get<Comment[]>('/comments')
}).subscribe(({ users, posts, comments }) => {
// All data loaded
});
}
// Émettre lors de changements
combineLatest([
this.http.get<User[]>('/users'),
this.http.get<Post[]>('/posts')
]).subscribe(([users, posts]) => {
// Process combined data
});
Bonnes Pratiques
- Toujours se désabonner ou utiliser le pipe
async - Utiliser les intercepteurs pour l'auth, le logging, les erreurs
- Typer vos réponses HTTP
- Gérer les erreurs de manière élégante
- Utiliser retry pour les échecs transitoires
- Annuler les requêtes avec
takeUntil()