Методы класса HttpClient после выполнения запроса возвращают объект Observable<any>, который определен в библиотеке RxJS ("Reactive Extensions"). Она не является непосредственно частью Angular, однако широко используется особенно при взаимодействии с сервером по http. Эта библиотека реализует паттерн "асинхронный наблюдатель" (asynchronous observable). Так, выполнение запроса к серверу с помощью класса HttpClient выполняются в асинхронном режиме.
Естественно чтобы задействовать функционал RxJS в приложении, в проект должна быть добавлена соответствующая зависимость "rxjs":
{
"name": "helloapp",
"version": "1.0.0",
"description": "First Angular 21 Project",
"author": "Eugene Popov <metanit.com>",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build"
},
"dependencies": {
"rxjs": "~7.8.1",
// остальное содержимое секции
},
"devDependencies": {
// содержимое секции
}
}
Используя специальные методы для объекта Observable, например, map и filter, можно произвести некоторую постобработку полученных от сервера результатов.
Так, возьмем проект из прошлой темы:
Например, определим в файле data.json данные, которые напрямую не соответствуют массиву объектов User:
{
"userList":
[{
"userName": "Bob",
"userAge": 28
},{
"userName": "Tom",
"userAge": 39
},{
"userName": "Alice",
"userAge": 32
}]
}
В качестве модели данных используем класс User, определенный в файле user.ts:
export class User{
constructor(public name:string, public age:number){}
}
То есть в данном случае у нас нет соответствия по именам свойствам: name - username и age - userage.
В файле http.service.ts определим следующий код сервиса, который будет получать данные из data.json:
import {Injectable} from "@angular/core";
import {HttpClient} from "@angular/common/http";
import {User} from "./user";
import {Observable} from "rxjs";
import { map } from "rxjs/operators";
@Injectable()
export class HttpService{
constructor(private http: HttpClient){ }
getUsers() : Observable<User[]> {
return this.http.get("assets/data.json").pipe(map((data:any)=>{
let usersList = data["userList"];
return usersList.map(function(user: any): User {
return new User(user.userName, user.userAge);
});
}));
}
}
Смысл использования специального сервиса для работы с http заключается в сокрытии деталей отправки запросов. Компонент же ожидает получить какие-то конкретные данные, например, в виде набора объектов User. С помощью метода map библиотеки rxjs можно преобразовать данные из одного формата в другой.
У результата метода get() мы можем вызвать метод pipe(), который позволяет обработать результаты запроса. Для этого
метод pipe в качестве первого параметра принимает функцию обработки данных запроса. В данном случае в роли такой функции выступает оператор map,
который преобразует результаты запроса в новые объекты.
Но чтобы использовать элементы библиотеки RxJS, их надо импортировать:
import {Observable} from "rxjs";
import { map } from "rxjs/operators";
В итоге весь метод getUsers() возвращает объект Observable<User[]>.
Теперь используем сервис в классе компонента:
import { Component, OnInit} from "@angular/core";
import { HttpService} from "./http.service";
import {User} from "./user";
@Component({
selector: "my-app",
template: `<ul>
@for(user of users; track $index){
<li>{{user?.name}} ({{user?.age}})</li>
}
</ul>`,
providers: [HttpService]
})
export class AppComponent implements OnInit {
users: User[]=[];
constructor(private httpService: HttpService){}
ngOnInit(){
this.httpService.getUsers().subscribe({next:(data: User[]) => this.users=data});
}
}