DevGang
Авторизоваться

RxJS: Введение в Subject в реактивном программировании 

Subjects - это «особый» тип наблюдаемых, который позволяет нам транслировать значения нескольким подписчикам. Самое интересное в Subjects, это то, что они обеспечивают ответ в реальном времени.

Например, если у нас есть subject с 10 подписчиками, всякий раз, когда мы передаем значения subject, мы можем видеть значение, полученное каждым подписчиком.

Это вводит пару проблем; Что делать, если мы нажимаем некоторые значения, а затем подписываемся или наоборот? Время играет важную роль: если мы подпишемся поздно, мы не сможем получить доступ к значениям, как если бы кто-то пришел на концерт в прямом эфире через 30 минут.

К счастью, у нас есть 4 типа subject, которые позволяют нам «путешествовать во времени», в которых мы можем получить доступ к значениям, даже если мы подписываемся поздно или нет.

Темы, которые мы рассмотрим:

  1. Что такое Subject с практическим примером
  2. BehaviorSubject: Получить последнее сообщение
  3. ReplaySubject: путешествие во времени
  4. AsyncSubject: после завершения получите последнее сообщение

1. Что такое Subject?

Как уже упоминалось, subject - это не что иное, как наблюдаемое с еще несколькими характеристиками. Наблюдаемый является по определению вызываемой коллекцией, которая генерирует данные после подписки. Между тем, субъект - это место, где мы контролируем состояние «когда передавать данные» нескольким подписчикам.

Субъект , позволяет вызывать методы , как  .next().complete()и  .error()снаружи, в то время как в наблюдаемом, мы вызываем эти методы как обратные вызовы.

// Создание Observable
const observable = new Observable((observer) => {
   observer.next(10);
   observer.next(5);
   observer.complete();
});

// Создание Subject
const subject = new Subject();
subject.next(10);
subject.next(5);
subject.complete();

Практический пример: давайте создадим простую группу чата, используя тему

Давайте представим, что мы создаем простое приложение для чата, где люди могут публиковать сообщения в чат-группе. Первым шагом является создание экземпляра субъекта, а затем его назначение chatGroup.

// Создать subject "Observable"
const chatGroup = new Subject();

Теперь, когда наша группа чата (Subject) создана, мы должны добавить сообщения. Давайте создадим типичный разговор между двумя друзьями.

// Отправляем значения в поток
chatGroup.next('David - Hi, which hot series do you recommend?');
chatGroup.next('Peter - Game of Thrones, Bodyguard or Narcos are few of the good ones');
chatGroup.next('David - Interesting, which one is the hottest?');
chatGroup.next('Peter - Game of Thrones!');

Пока все хорошо - теперь у нас есть 4 сообщения в нашей группе чатов, что будет, если мы подпишемся? Или, скажем, новый друг по имени Джон хочет присоединиться к разговору. Он сможет увидеть старые сообщения?

// Распечатаем сообщения
chatGroup.subscribe((messages) => {
   console.log(messages)
})

К сожалению, нет, Джон пропускает разговор, потому что подписывается поздно. Это прекрасный пример того, как работает реактивное программирование - идея о значениях, проходящих со временем, и, следовательно, мы должны подписаться в нужное время, чтобы получить доступ к значениям.

Чтобы более подробно остановиться на предыдущем примере, что если Джон войдет в середину разговора?

// Отправляем значения в поток
chatGroup.next('David - Hi, which hot series do you recommend?');
chatGroup.next('Peter - Game of Thrones, Bodyguard or Narcos are few of the good ones');

// Джон вступает в разговор
chatGroup.subscribe((messages) => {
   console.log(messages)
});

chatGroup.next('David - Interesting, which one is the hottest?');
chatGroup.next('Peter - Game of Thrones!');

// Сообщения которые получит Джон
// David - Interesting, which one is the hottest?
// Peter - Game of Thrones!

Как только Джон подписывается, он видит два последних сообщения. Subject делает то, что должен делать. Но что, если мы хотим, чтобы Джон просмотрел все сообщения или только последнее, или получил уведомление при публикации нового сообщения?

В целом, эти subject в основном похожи, но каждый из них предоставляет некоторые дополнительные функции, давайте опишем их один за другим.

2. BehaviorSubject: Получить последнее сообщение

BehaviorSubject похож на Subject, за исключением того, что ему требуется начальное значение в качестве аргумента для обозначения начальной точки потока данных. Причина в том, что когда мы подписываемся, возвращается последнее сообщение. Это аналогичная концепция при работе с массивами; где мы делаем, array.length-1 чтобы получить последнее значение.

import { BehaviorSubject } from "rxjs";

// Создаем Subject
const chatGroup = new BehaviorSubject('Starting point');

// Отправляем значения в поток
chatGroup.next('David - Hi, which hot series do you recommend?');
chatGroup.next('Peter - Game of Thrones, Bodyguard or Narcos are few of the good ones');
chatGroup.next('David - Interesting, which one is the hottest?');
chatGroup.next('Peter - Game of Thrones!');

// Джон подключается к потоку
chatGroup.subscribe((messages) => {
   console.log(messages)
})

// Сообщения которые видит Джон
// Peter - Game of Thrones!

3. ReplaySubject: путешествие во времени

ReplaySubject, как следует из названия, после подписки транслирует все сообщения, несмотря на то, что мы подписались поздно или нет. Это как путешествие во времени, где мы можем получить доступ ко всем сообщениям, которые были переданы.

import { ReplaySubject } from "rxjs";

// Создаем Subject
const chatGroup = new ReplaySubject();

// Отправляем значения в поток
chatGroup.next('David - Hi, which hot series do you recommend?');
chatGroup.next('Peter - Game of Thrones, Bodyguard or Narcos are few of the good ones');
chatGroup.next('David - Interesting, which one is the hottest?');
chatGroup.next('Peter - Game of Thrones!');

// Джон подключается к потоку
chatGroup.subscribe((messages) => {
   console.log(messages)
})

// Сообщения которые видит Джон
// David - Hi, which hot series do you recommend?'
// Peter - Game of Thrones, Bodyguard or Narcos are few of the good ones'
// David - Interesting, which one is the hottest?'
// Peter - Game of Thrones!'

4. AsyncSubject: после завершения получите последнее сообщение

AsyncSubject похож на BehaviorSubject с точки зрения выдачи последнего значения после подписки. Единственное отличие состоит в том, что для этого требуется complete()метод, помечающий поток как завершенный. Как только это будет сделано, будет выпущено последнее значение.

import { AsyncSubject } from "rxjs";

// Создаем Subject
const chatGroup = new AsyncSubject();

// Отправляем значения в поток
chatGroup.next('David - Hi, which hot series do you recommend?');
chatGroup.next('Peter - Game of Thrones, Bodyguard or Narcos are few of the good ones');
chatGroup.next('David - Interesting, which one is the hottest?');
chatGroup.next('Peter - Game of Thrones!');

chatGroup.complete(); // <-- пометить поток как завершенный

// Джон подключается к потоку
chatGroup.subscribe((messages) => {
   console.log(messages)
})

// Сообщения которые видит Джон
// Peter - Game of Thrones!'

Резюме

Возвращаясь к нашему предыдущему примеру с Джоном, мы теперь можем решить, хотим ли мы, чтобы Джон имел доступ ко всему диалогу (ReplaySubject), последнему сообщению (BehaviorSubject) или последнему сообщению после завершения диалога (AsyncSubject).

#RxJS
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу