LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 2617 min read

HttpClient & Fetching Data

Make HTTP requests from an Angular service using the built-in HttpClient, and expose the results through Observables.

Providing HttpClient

HttpClient must be enabled once, app-wide, via provideHttpClient() in your application config.

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [provideHttpClient()],
};

Making a GET Request

A service wraps HttpClient calls, keeping components free of HTTP-specific logic. Every HttpClient method returns an Observable, not a Promise.

// posts.service.ts
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({ providedIn: 'root' })
export class PostsService {
private http = inject(HttpClient);
getPosts() {
return this.http.get<Post[]>('/api/posts'); // returns Observable<Post[]>
}
}

Consuming It in a Component

A component subscribes to the returned Observable to actually trigger the request and receive its result.

import { Component, OnInit, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PostsService } from './posts.service';
@Component({
selector: 'app-posts',
standalone: true,
imports: [CommonModule],
template: `
<ul>
<li *ngFor="let post of posts">{{ post.title }}</li>
</ul>
`,
})
export class PostsComponent implements OnInit {
private postsService = inject(PostsService);
posts: Post[] = [];
ngOnInit() {
this.postsService.getPosts().subscribe(posts => {
this.posts = posts;
});
}
}
Or Use the async Pipe

Assigning the Observable itself to a posts$ property and using {{ (posts$ | async) }} in the template (covered in the pipes lesson) avoids manually subscribing and unsubscribing entirely.

POST, PUT, and DELETE

createPost(title: string) {
return this.http.post<Post>('/api/posts', { title });
}
updatePost(id: number, title: string) {
return this.http.put<Post>(`/api/posts/${id}`, { title });
}
deletePost(id: number) {
return this.http.delete<void>(`/api/posts/${id}`);
}

Typing the Response

Passing a generic type to any HttpClient method gives you full TypeScript autocomplete and checking on the response shape.

interface Post {
id: number;
title: string;
}
getPosts() {
return this.http.get<Post[]>('/api/posts');
}

Common Beginner Mistakes

Forgetting to subscribe to an Observable

HttpClient requests are lazy — nothing actually happens until you .subscribe() (or use the async pipe); an unused Observable never fires the request.

Not unsubscribing from a manually-subscribed Observable

A component that manually calls .subscribe() should unsubscribe in ngOnDestroy, unless the Observable is guaranteed to complete on its own (like most single-response HTTP requests do).

FAQs

Observables support cancellation, retries, and powerful operator chaining (covered in the RxJS lessons) that Promises don't — a deliberate design choice for handling real-world HTTP concerns.

Yes — the firstValueFrom() (or lastValueFrom()) RxJS utility converts an Observable into a Promise, letting you await a single HTTP response if you prefer that style.

Summary

HttpClient gives you a typed, Observable-based way to talk to a backend, wrapped cleanly inside a service. Next, you'll go deeper into RxJS and Observables themselves.

Next Lesson →

RxJS & Observables Basics