The HTTP Client
Angular's HttpClient is how components and services talk to a backend API — every method returns an Observable rather than a value or a Promise directly.
Making a GET request
TS user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
interface User {
id: number;
name: string;
}
@Injectable({ providedIn: 'root' })
export class UserService {
constructor(private http: HttpClient) {}
getUser(id: number) {
return this.http.get<User>(`/api/users/${id}`);
}
}
this.http.get<User>(...) doesn't make the request yet — it returns an Observable<User> describing a request that will run once something subscribes to it.
Subscribing to actually fire the request
TS profile.component.ts
export class ProfileComponent {
user: User | null = null;
constructor(private userService: UserService) {}
ngOnInit() {
this.userService.getUser(42).subscribe(user => {
this.user = user;
});
}
}
Behavior
The HTTP GET request only fires once .subscribe() is called. When the response arrives, the callback runs and this.user is set, which triggers the template to re-render with the data.
ngOnInit is a lifecycle hook that runs once, right after Angular finishes setting up the component — a natural place to kick off an initial data load.
Handling errors
TS profile.component.ts — with error handling
this.userService.getUser(42).subscribe({
next: user => { this.user = user; },
error: err => { console.log('Failed to load user:', err.message); }
});
The object form of .subscribe() lets you handle a failed request explicitly — without an error handler, a failed HTTP call fails silently as far as the rest of your component is concerned.
Note: because
HttpClient methods return Observables rather than Promises, calling .get() and never subscribing means the request is never sent at all — this trips up people coming from fetch(), where the request fires the moment you call it. It's also why forgetting to unsubscribe from a long-lived subscription (rather than a one-shot HTTP call, which completes on its own) can leak memory in a component that gets destroyed and recreated repeatedly, like inside a router-outlet.