Сборник важных советов о RxJS, которые вы могли не знать

[ Эта статья и любые обновления публикуются на allfront.io. ]

Что здесь скрыто?

Давайте перейдем к делу; В этой статье кратко освежается RxJS и приводятся практические советы по использованию RxJS. Мы также рассмотрим наиболее распространенные операторы и вещи, на которые следует обратить внимание. В конце статьи мы также рассмотрим предложения по инструментам, которые значительно улучшат вашу отладку rxjs.

Что такое RxJS?

Чтобы процитировать официальную документацию:

RxJS (или реактивные расширения для javascript) — это библиотека для составления асинхронных и событийных программ с использованием наблюдаемых последовательностей.

Одна из лучших вещей в RxJS — читабельность. Вы можете смешивать асинхронную и синхронную логику, а также использовать сотни готовых операторов, которые также хорошо задокументированы и протестированы, что позволяет выполнять всевозможные асинхронные операции очень быстро. Существуют также инструменты отладки для отладки и улучшения наблюдаемого конвейера.

Другие интересные функции включают в себя:
✍ Возможность отмены,
🚩 Обработка ошибок довольно аккуратная,
⚡ Возможность прослушивать результат наблюдения в нескольких местах.

К чему все эти разговоры о трубах?

Давайте разберемся с терминологией:

  • В Модели вытягивания потребитель данных имеет всю власть — потребитель решает, когда он получит данные.
  • В модели Push повелители производителей решают, когда вы получите свои данные. (см. пример ниже)
  • Потоки — это последовательность значений данных во времени.
  • Наблюдаемые объекты – это потоки данных, которые могут возвращать поток значений наблюдателю за определенный период времени. Вы также можете просматривать Observables как ленивые коллекции push.
  • Наблюдатели являются потребителями Observables
  • Операторы — это функции, которые изменяют или создают наблюдаемые объекты. Есть два основных типа операторов; Конвейерные операторы — это функции, которые возвращают другой наблюдаемый объект, а операторы создания — это автономные функции, которые создают новые наблюдаемые объекты.

Реализация наблюдаемых

Давайте пройдемся по жизни Observable и объясним общие и важные вещи, которые нужно знать:

Создание

В RxJS мы чаще всего используем операторы создания, такие как of, from и intervalдля создания Observable. Посетите сайт Learnrxjs.io, чтобы узнать, как создать Observable.

Подписка

Для того, чтобы получать какие-либо данные из Observables, вам необходимо подписаться на них. Официальная документация описывает подписку следующим образом:

"Подписка на Observable похожа на вызов функции, предоставляющей обратные вызовы, куда будут доставлены данные".

"это просто способ начать выполнение Observable"

Здесь следует отметить одно ключевое различие между Observables и нативным addEventListener, которое заключается в том, что Observables не поддерживает список подключенных наблюдателей.

выполнение

Чтобы отправить свежие данные в Observable, мы можем использовать одно из следующих уведомлений:

  • next(1)используется для отправки свежих данных в поток
  • error() — уведомляет Observers об ошибке. Завершает поток.
  • complete() — уведомляет наблюдателей о том, что наблюдаемое завершено. Завершает поток.

Когда поток завершается, это означает, что подписчики перестают получать информацию от Observable. На практике это означает, что если у вас есть три компонента, подписанных на Observable, получающий данные из API, который возвращает ошибку HTTP 403 на ресурсе, если вы не обработаете его должным образом, эти компоненты больше не будут получать данные из этого потока.

Утилизация

Чтобы избежать утечек подписки и памяти, важно убивать мошеннические подписки и освобождать память. Это можно сделать с помощью .unsubscribe, однако мы предлагаем использовать take, takeUntil или ng-neat/until-destroy, которые обеспечивают удобный и понятный способ отписаться с помощью декораторов. В следующем фрагменте показаны все 3 возможных способа уничтожения подписок:

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

Потеря шариков с мраморными диаграммами

Мраморные диаграммы могут выглядеть пугающе, но они не так сложны, как могут показаться. Ознакомьтесь с Проектом Rx Visualiser, чтобы получить интерактивное представление о мраморных диаграммах.

После того, как вы поиграетесь с сайтом, вернитесь сюда и посмотрите на следующую аккуратную иллюстрацию из официальной документации:

В чем разница между субъектами и наблюдаемыми?

Возможно, вы заметили, что в одном из моих ранних примеров субъект использовался для уничтожения наблюдаемого.

Проще говоря, Subjects — это специальные Observables, которые позволяют вам отправлять значения после того, как они были созданы.

Наш быстрый совет по предметам: когда вы их используете, выставляйте только Observable, а не весь предмет:

Предоставление всей темы — это эквивалент общедоступной переменной, которую каждый может изменить — любой может писать в этот поток. Если вы предоставляете только наблюдаемое, оно фактически доступно только для чтения, и вы можете только слушать.

Проблема, с которой вы можете столкнуться при использовании субъектов, заключается в том, что они «не помнят» значения. Вот почему вы, вероятно, видите, что BehaviourSubjects используется чаще. BehaviorSubjects дополнительно увеличивает количество тем, сохраняя значение. Всякий раз, когда вы подписываетесь на него, он немедленно возвращает последнее значение. Если вы хотите, чтобы он давал вам значение, когда оно есть, используйте это:

BehaviorSubjects широко используются для поддержания состояния приложения в приложениях малого и среднего размера. Однако, если вы строите что-то более сложное, мы рекомендуем использовать NgRx с фасадами.

Полезные операторы

Документация включает в себя исчерпывающий список операторов с примерами, но они могут быть довольно громоздкими для начинающих — вот то, что мы считаем необходимым для начала:

Ознакомьтесь с основными операторами карты и фильтра — это невероятно полезные операторы, которые вы будете использовать изо дня в день. FlatMap подходит, когда вы хотите уменьшить вложенность наблюдаемых объектов до одного уровня (таким образом, выравнивая вложенность наблюдаемых объектов).

Для тестирования часто требуются наблюдаемые объекты, которые никогда не выдают, не выдают пустое значение или не выдают ошибку. В этих случаях вы должны научиться использовать Never Empty и Throw

tap или do можно легко использовать в каналах для отладки и поиска проблем (подробнее об этом чуть позже).

Сокращение выполнения конвейера может привести к значительному повышению производительности как для серверной, так и для внешней части. debounceTime и auditTime обычно находятся в полях поиска, поскольку они удаляют выполнения, которые очень близки друг к другу (по времени), а также уменьшают использование полосы пропускания на внешнем интерфейсе. distinctUntilChanged также может быть полезен во многих случаях, например, для прослушивания событий браузера, таких как прокрутка и движение мыши.

Операторы высшего порядка

Операторы более высокого порядка используются, когда нам нужно хранить Observables внутри Observables. Это может показаться крайним случаем, но на самом деле это довольно распространенное явление. Пример этого можно увидеть, когда нам нужно последовательно вызвать 2 API (второй вызов API зависит от вывода первого). Например: аутентифицировать пользователя, а затем получить информацию об этом пользователе.

Как правило, вложенные подписки — это антишаблон.

Вложенных подписок всегда можно избежать, используя операторы более высокого порядка, такие как switchMap, mergeMap/flatMap, combLatest.

Давайте быстро пробежимся по некоторым из наиболее распространенных HOO:

concat и concatMap

Этот оператор последовательно объединяет 2 потока. Complete необходимо вызвать в первом потоке, прежде чем второй поток сможет начать возвращать значения.

SwitchMap

SwitchMap сводит на нет необходимость вложенных подписок, переключаясь на внутренний наблюдаемый объект.

ОбъединитьПоследние

CombineLatest выдает все значения из своих наблюдаемых всякий раз, когда в одном из потоков происходит изменение:

В чем разница между горячими и холодными наблюдаемыми?

Холодные наблюдаемые создают данные сами, в то время как горячие наблюдаемые полагаются на внешние факторы. Давайте воспользуемся для этого примером:

import {BehaviorSubject, interval, of} from 'rxjs';
import {map} from 'rxjs/operators';


export class HotVsCold {

  // cold observable demo
  coldObservable$ = of(['The', 'data', 'is', 'all', 'here']);

  coldObservableDemo() {
    //  each subscription re-creates the data
    this.coldObservable$.subscribe((streamData) => {
      console.log(streamData);
    });

    this.coldObservable$.subscribe((streamData) => {
      console.log(streamData);
    });
  }

  // hot observable demo
  hotObservable$ = new BehaviorSubject(1);

  hotObservableDemo() {
    // increment the hotobservable number every second
    interval(1000).pipe(
      map(() => this.hotObservable$.getValue()),
    ).subscribe((data) => {
      this.hotObservable$.next(data + 1);
    });

    //  each subscription listens to the same set of data
    this.hotObservable$.subscribe((streamData) => {
      console.log(streamData);
    });

    this.hotObservable$.subscribe((streamData) => {
      console.log(streamData);
    });
  }
}

Улучшение ваших труб

Устранение проблем с трубопроводами вызывает головную боль у сантехников RxJS по всему миру. Вы можете использовать do/tap для поиска проблем в коде, однако есть и более эффективные способы отладки проблем.

Одним из таких способов является использование библиотеки rxjs-spy. Вы можете добавлять теги в свои каналы и регистрировать только те теги, когда это необходимо:

Библиотека также упрощает отслеживание подписок, показывая количество подписок, которые есть у помеченных наблюдаемых объектов:

Это делает его идеальным для отладки утечек подписки.

Заключительные мысли

RxJS — очень мощная библиотека, которая может упростить код и сделать его более читабельным. Есть также дополнительные инструменты, которые можно установить, чтобы дать вам еще больше власти над вашими данными. Как только вы поймете мраморные диаграммы, они также станут отличным способом объяснить операторы.

Мы надеемся, что вам понравилась эта статья о RxJS и что она оказалась полезной! Пожалуйста, не забудьте оставить комментарий, если вы считаете, что я упустил важный лакомый кусочек, или подпишитесь на дополнительный контент!