HttpClient: отправка данных и ошибки
Чтобы создать запись на сервере, отправляют POST-запрос с данными в теле. Любой запрос может не удаться: нет сети, сервер вернул 404 или 500. Пользователь должен видеть и загрузку, и понятное сообщение об ошибке.
POST-запрос
Добавьте метод в сервис PostApi:
// src/app/post-api.ts
createPost(data: { title: string; body: string }) {
return this.http.post<Post>(this.url, { ...data, userId: 1 });
}Второй аргумент post() — тело запроса. HttpClient сам превращает объект в JSON и ставит заголовок Content-Type: application/json. Так же работают put(), patch() и delete().
Вызов из компонента
ng generate component post-form// src/app/post-form/post-form.ts
import { Component, inject, signal } from '@angular/core';
import { PostApi } from '../post-api';
@Component({
selector: 'app-post-form',
templateUrl: './post-form.html',
})
export class PostForm {
private api = inject(PostApi);
message = signal('');
save(title: string, body: string) {
this.api.createPost({ title, body }).subscribe((post) => {
this.message.set(`Статья создана, id = ${post.id}`);
});
}
}<!-- src/app/post-form/post-form.html -->
<input #title placeholder="Заголовок" />
<textarea #body placeholder="Текст"></textarea>
<button (click)="save(title.value, body.value)">Опубликовать</button>
<p>{{ message() }}</p>После нажатия появится «Статья создана, id = 101». JSONPlaceholder отвечает так, будто сохранил статью, но на самом деле ничего не записывает — для учёбы это удобно.
Загрузка и ошибка
Объект с полями next и error в subscribe() позволяет обработать оба исхода:
// src/app/post-list/post-list.ts
import { Component, OnInit, inject, signal } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import { PostApi } from '../post-api';
import { Post } from '../post';
@Component({
selector: 'app-post-list',
templateUrl: './post-list.html',
})
export class PostList implements OnInit {
private api = inject(PostApi);
posts = signal<Post[]>([]);
loading = signal(true);
error = signal('');
ngOnInit() {
this.api.getPosts().subscribe({
next: (posts) => {
this.posts.set(posts);
this.loading.set(false);
},
error: (err: HttpErrorResponse) => {
this.error.set(`Не удалось загрузить статьи (код ${err.status})`);
this.loading.set(false);
},
});
}
}<!-- src/app/post-list/post-list.html -->
@if (loading()) {
<p>Загрузка...</p>
} @else if (error()) {
<p class="error">{{ error() }}</p>
} @else {
@for (post of posts(); track post.id) {
<h3>{{ post.title }}</h3>
}
}Чтобы проверить ошибку, поменяйте адрес в сервисе на несуществующий, например /postsx, — появится «Не удалось загрузить статьи (код 404)». Без сети код будет 0.
Запасное значение через catchError
Иногда ошибку лучше обработать в сервисе и вернуть пустой список:
// src/app/post-api.ts
import { catchError, of } from 'rxjs';
getPostsSafe() {
return this.http.get<Post[]>(this.url).pipe(
catchError(() => of([])),
);
}Функция of([]) создаёт Observable с одним значением — пустым массивом. Компонент получит [] и покажет блок @empty.
Частая ошибка
Не обрабатывать ошибку совсем. Тогда при сбое индикатор «Загрузка...» висит вечно, а ошибка видна только в консоли браузера. У каждого запроса, результат которого видит пользователь, должна быть ветка error или оператор catchError.