Что такое observable angular
Методы класса HttpClient после выполнения запроса возвращают объект Observable , который определен в библиотеке RxJS («Reactive Extensions»). Она не является непосредственно частью Angular, однако широко используется особенно при взаимодействии с сервером по http. Эта библиотека реализует паттерн «асинхронный наблюдатель» (asynchronous observable). Так, выполнение запроса к серверу с помощью класса HttpClient выполняются в асинхронном режиме.
Естественно чтобы задействовать функционал RxJS в приложении, в проект должна быть добавлена соответствующая зависимость «rxjs»:
< "name": "helloapp", "version": "1.0.0", "description": "First Angular 16 Project", "author": "Eugene Popov ", "scripts": < "ng": "ng", "start": "ng serve", "build": "ng build" >, "dependencies": < "rxjs": "7.5.0", // остальное содержимое секции >, "devDependencies": < // содержимое секции >>
Используя специальные методы для объекта Observable, например, map и filter , можно произвести некоторую постобработку полученных от сервера результатов.
Так, возьмем проект из прошлой темы:
Например, определим в файле users.json данные, которые напрямую не соответствуют массиву объектов User:
В качестве модели данных используем класс User:
export class User < constructor(public name:string, public age:number)<>>
То есть в данном случае у нас нет соответствия по именам свойствам: name — username и age — userage.
Определим следующий код сервиса, который будет получать данные из users.json:
import from '@angular/core'; import from '@angular/common/http'; import from './user'; import from 'rxjs'; import < map >from 'rxjs/operators'; @Injectable() export class HttpService < constructor(private http: HttpClient)< >getUsers() : Observable< return this.http.get('assets/users.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 from 'rxjs'; import < map >from 'rxjs/operators';
В итоге весь метод getUsers() возвращает объект Observable
Теперь используем сервис в классе компонента:
Объект Observable¶
Объекты RxJS Observable создаются либо с использованием операторов создания ( of , from , fromEvent ), либо через new Observable .
Пример с оператором of() .
of('Hello').subscribe((vl) => console.log(vl));
Пример с new Observable .
1 2 3 4 5 6 7 8 9 10
const obs = new Observable((sub) => sub.next(1); setTimeout(() => sub.next(3); sub.complete(); >, 500); >); obs.subscribe((vl) => console.log(vl));
Каждый Observable может отправлять своим «потребителям» уведомления вызовом одного из трех методов:
- next() — отправка данных, количество вызовов не ограничено;
- error() — генерация ошибки, параметром указываются данные любого формата (строка, объект, исключение) о причине ее возникновения;
- complete() — завершение исполнения Observable , не принимает никаких параметров и не передает никакого значения.
Но исполнение RxJS Observable начнется только после вызова у него метода subscribe() , который принимает функцию с передаваемыми данными в качестве аргумента. Вторым и третьим необязательными параметрами методу subscribe() можно передать функции, которые будут вызваны в случае ошибки или (и) завершения Observable .
1 2 3 4 5 6 7 8 9 10 11 12 13
const obs = new Observable((sub) => sub.next(1); setTimeout(() => sub.error(3); >, 500); >); obs.subscribe( (vl) => console.log(vl), (err) => console.log('Error: ', err), () => console.log('Completed') );
Вызов error() или complete() автоматически завершает исполнение Observable .
Количество вызовов исполнения такого объекта не ограничено, а сам он даже не знает, сколько «потребителей» получают от него данные.
Метод subscribe() возвращает объект типа Subscription , который хранит текущее исполнение конкретного RxJS Observable и имеет единственный метод unsubscribe() для отмены его исполнения.
1 2 3
const sub = obs.subscribe(); sub.unsubscribe();
Вызов unsubscribe() нужен только для бесконечно исполняемых Observable , иначе занимаемые ими ресурсы будут освобождены только с окончанием работы всего приложения. А значит в процессе работы программы может произойти утечка памяти или могут быть созданы ненужные дублирующиеся «потребители».
Например, последнее может произойти, когда пользователь зашел на страницу, инициирующую исполнение RxJS Observable , затем перешел на другой URL и вернулся обратно.
Бесконечно исполняемыми Observable считаются те из них, которые никогда не вызывают метод complete() , даже если у них предусмотрен сценарий, при котором произойдет обращение к error() , что также завершит исполнение.
В Angular приложении unsubscribe() обычно вызывается на стадии жизненного цикла OnDestroy() того компонента, в котором используется Observable .
Что такое observable angular
Observable — это название механизма, который используется в Angular для программирования асинхронных потоков данных в декларативном стиле. Observable является синонимом термина stream . К асинхронным потокам данных обычно относятся такие концепции, как события, http запросы и триггеры в коде.
Данный механизм позволяет создавать объекты, инициирующие асинхронные потоки (stream или observable) и объекты, которые за ними наблюдают (observer).
Над observable можно производить различные операции, например, их можно создавать, комбинировать и фильтровать. Более того практически все что угодно может быть потоком. Потоковое программирование это очень гибкая концепция, позволяющая реализовывать необходимую логику минимальным количеством кода.
Для расширенной реализации observable в Angular используется сторонняя библиотека Reactive Extensions (RxJS).
Работа с потоками стоится на двух объектах — observable и observer. Эти методы представляет один и тот же объект, что делает удобным реализацию данного механизма в виде сервиса.
Observableимеет 3 состояния:
- обработка данных
- успешное завершение обработки
- ошибка обработки
Interval
rxjs/Rx — дает дополнительные возможности для Observable . Создадим объект класса Observable , который будет отправлять и принимать сообщения. Для отправки сообщений используем метод interval() , который отправляет последовательные числа от нуля через заданный промежуток времени. Для приема сообщений используем метод subscribe() , в который передадим callback , выводящий каждое сообщение в консоль.
import < Component, OnInit >from '@angular/core'; import < Observable >from 'rxjs/Observable'; import 'rxjs/Rx'; //. export class HomeComponent implements OnInit < //. ngOnInit() < const obsExample = Observable.interval(1000); obsExample.subscribe( num =>console.log(num) ); > >
Создание своего Observable
У класса Observable есть метод create() , который создает новый экземпляр Observable .
import < Component, OnInit >from '@angular/core'; import < Observable >from 'rxjs/Observable'; import < Observer >from 'rxjs/Observer'; import 'rxjs/Rx'; //. const myObservable = Observable.create((observer: Observer) => < setTimeout(() =>< observer.next('first package'); >, 2000); setTimeout(() => < observer.next('second package'); >, 4000); setTimeout(() => < // observer.error('this does not work'); observer.complete(); >, 5000); setTimeout(() => < observer.next('third package'); >, 6000); >); myObservable.subscribe( (data: string) => < console.log(data); >, (error: string) => < console.log(error); >, () => < console.log('completed'); >);
Unsubscribe
Для отписки от события, используется метод unsubcribe() класса Subscription .
Пример реализации отписки в методе ngOnDestroy() :
import < Component, OnInit, OnDestroy >from '@angular/core'; import < Observable >from 'rxjs/Observable'; import < Observer >from 'rxjs/Observer'; import < Subscription >from 'rxjs/Subscription'; import 'rxjs/Rx'; //. export class HomeComponent implements OnInit, OnDestroy < customSubscription: Subscription; constructor() < >ngOnInit() < const myObservable = Observable.create((observer: Observer) => < //. >); this.customSubscription = myObservable.subscribe( //. ); > ngOnDestroy() < this.customSubscription.unsubscribe(); >>
Взгляд сверху: что такое Observable
Observable – асинхронный паттерн проектирования, в котором данные представлены в виде потока событий. Потоки можно «переиспользовать» – комбинировать, фильтровать, подобно массивам, используя специальные методы – операторы.
Весь список операторов управления потоками доступен на странице официальной документации библиотеки RxJS, являющейся реализацией спецификации Observable.
Браузерная среда подразумевает асинхронное взаимодействие с пользователем – реакция на клики, действия мышкой и клавиатурой, отправка и получение данных с помощью Ajax-запросов, да и просто загрузка ресурсов.
Существуют другие подходы для обработки и группировки асинхронных событий: callbacks, Promises, async/await. Паттерн Observable, в отличие от них, является «макро-паттерном» и позволяет вынести логику обработки и управления асинхронными событиями на отдельный слой приложения.
В Angular модель Observable является внутренним стандартом при отправке и получении событий и данных между участниками приложения – компонентами и сервисами.
Библиотека RxJS не включена в стандартную сборку Angular, однако может быть легко интегрирована для удобства использования операторов. Как – можно подсмотреть здесь.
Есть вопрос? Нужна консультация? Напишите в комментариях!