Объект Observable и библиотека RxJS

Последнее обновление: 15.11.2023

Методы класса HttpClient после выполнения запроса возвращают объект Observable<any>, который определен в библиотеке RxJS ("Reactive Extensions"). Она не является непосредственно частью Angular, однако широко используется особенно при взаимодействии с сервером по http. Эта библиотека реализует паттерн "асинхронный наблюдатель" (asynchronous observable). Так, выполнение запроса к серверу с помощью класса HttpClient выполняются в асинхронном режиме.

Естественно чтобы задействовать функционал RxJS в приложении, в проект должна быть добавлена соответствующая зависимость "rxjs":

{
    "name": "helloapp",
    "version": "1.0.0",
    "description": "First Angular 17 Project",
    "author": "Eugene Popov <metanit.com>",
    "scripts": {
        "ng": "ng",
		"start": "ng serve",
		"build": "ng build"
    },
    "dependencies": {
        "rxjs": "~7.8.0",
		// остальное содержимое секции
    },
    "devDependencies": {
        // содержимое секции
    }
}

Используя специальные методы для объекта Observable, например, map и filter, можно произвести некоторую постобработку полученных от сервера результатов.

Так, возьмем проект из прошлой темы:

RxJS и Observable в Angular

Например, определим в файле 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.

Определим следующий код сервиса, который будет получать данные из users.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 { HttpClientModule} from "@angular/common/http";

import { HttpService} from "./http.service";
import {User} from "./user";

@Component({
    selector: "my-app",
    standalone: true,
    imports: [HttpClientModule],
    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});
    }
}
Загрузка данных json и их преобразование с RxJs в Angular
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850