Реактивно с RXJS

Нажмите здесь, чтобы опубликовать эту статью в LinkedIn »

Я занимаюсь реактивным программированием почти два года, и мне почти невозможно даже думать без него. Реактивный способ кодирования более наглядно представляет реальные сценарии.

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

В вычислительной технике реактивное программирование - это декларативная парадигма программирования, касающаяся потоков данных и распространения изменений. (источник википедия)

Предпосылки

  • Javascript (лучше, если вы знаете javascript)
  • Узел и npm
  • HTTP и Rest API
  • Фреймворк Javascript (в этой статье я буду использовать angular 2x)

Асинхронное и реактивное программирование

Асинхронное программирование - это форма параллельного программирования, которая позволяет единице работы работать отдельно от основного потока приложения. Когда работа завершена, он уведомляет основной поток (а также, была ли работа завершена или не удалась). Его использование дает множество преимуществ, таких как улучшенная производительность приложений и повышенная скорость отклика. (Источник stackify.com)

Короче говоря, это асинхронное программирование. Итак, изначально, когда я начал кодировать, интерфейс был просто html-страницами. Асинхронность - это нормально, но когда я перешел на Angular js и начал использовать ng-repeat, все стало запутаться. Поскольку мой код Angular не ждал завершения моих асинхронных вызовов, а моя страница была просто пустой ... облом.

Затем мы начали использовать обратные вызовы. Обратные вызовы - это просто код, который выполняется после выполнения определенной операции, например, вызов ajax.

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

Далее мы попытались решить эти обещания. Это просто более крутая версия обратного вызова с некоторыми четко определенными API, такими как then и catch.

Promise - это прокси для значения, не обязательно известного на момент создания обещания. Он позволяет связать обработчики с конечным значением успеха или причиной сбоя асинхронного действия. Это позволяет асинхронным методам возвращать значения, как синхронные методы: вместо того, чтобы немедленно возвращать окончательное значение, асинхронный метод возвращает обещание предоставить значение в какой-то момент в будущем. ("источник")

Promise находится в одном из следующих состояний:

  • ожидает: начальное состояние, ни выполнено, ни отклонено.
  • выполнено: означает, что операция успешно завершена.
  • отклонено: это означает, что операция не удалась.

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

Ну, а затем идет Observable, который представляет собой просто многоразовое обещание, которое продолжает прослушивание после метода then. Это похоже на то, что вы даже можете получить значение из наблюдаемого, если затем сработало один раз, а наблюдаемое выдало новое значение. Единственное отличие состоит в том, что вместо then у наблюдаемого метода есть метод subscribe.

Образец наблюдателя

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

В оставшейся части этой статьи я хочу, чтобы вы визуализировали свои данные как поток событий или обновлений. Хорошо, теперь мы понимаем основы асинхронного JavaScript и реактивного программирования. Мы узнали об эволюции от обратных вызовов к обещаниям и наблюдаемым. Мы узнали о данных как о потоке.

Давайте напишем код

Настроить угловой проект

Что ж, если вы уже знакомы с angular, вы знаете, что теперь у нас есть cli для автоматической загрузки нашего проекта. Если у вас его нет, вы можете установить его, выполнив команду ниже в своем терминале.

sudo npm install -g @angualar/cli
ng new ngrxjs
cd ngrxjs
ng serve

Теперь вы можете перейти на http: // localhost: 4200, чтобы увидеть, готов ли ваш проект angular и обслуживается (пожалуйста, дождитесь завершения вышеуказанной задачи перед переходом)

Создайте наблюдаемый

Теперь мы собираемся создать нашу самую первую наблюдаемую, используя самый простой оператор под названием create (более подробно объясненный здесь).

Пожалуйста, напишите следующий код в файле src / app / app.component.ts внутри вашего вновь созданного проекта.

В строке 16 мы создали новую наблюдаемую. Проще говоря, наблюдаемые являются предметом в шаблоне проектирования наблюдателя, мы наблюдаем за ними, чтобы генерировать их для любых обновлений.

В строке 23 мы подписываемся на this is observable, передавая ему объект-наблюдатель, в котором есть три функции.

  • Следующий
  • Ошибка
  • Полный

Здесь они переданы как три функции, что почти то же самое, что и передача этих функций в объект-наблюдатель. Итак, если вы вернетесь к строке 17, мы запускаем next () пару раз, поэтому каждый раз, когда мы запускаем next для наблюдателя, мы получаем обновление внутри подписки next, которое является методом в строке 24, и, наконец, когда вызывается завершение для наблюдателя, Третий метод вызывается для вывода «это конец».

Если все в порядке и ваш сервер работает по адресу http: // localhost: 4200, вы должны увидеть в консоли браузера следующие выходные данные журнала консоли.

Предмет

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

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

Так, например, если в приведенном выше коде вы хотите выйти из блока кода 16–21, вы не можете выполнять Observer.next (). Но если вы хотите сделать что-то подобное, т.е. хотите запускать следующий, когда захотим.

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

В приведенном выше коде вы можете видеть, что мы сделали подписку в строке 17, а позже мы запускаем ее дальше. Тема может быть очень удобна, чтобы активировать ее рядом с трансляцией обновленного значения всем наблюдателям всякий раз, когда нам нужно.

Поведение Субъект

Субъект поведения похож на объект с дополнительной функцией, которой требуется начальное значение при создании экземпляра. И при первой подписке вы получаете это значение, в отличие от темы, где после подписки вам нужно запустить следующую хотя бы один раз, чтобы получить значение в подписке.

Итак, теперь в строке 18 подписка получит начальное значение 100, даже не передавая первое следующее значение.

Повторить тему

Что ж, это кажется довольно хорошим, но как в BehaviorSubject, так и в Subject вы получаете только последнее значение, но что, если вам нужны все значения, которые передаются субъектом с самого начала. Не беспокойтесь, у нас есть ReplaySubject для этого, replaysubject сохранит все значения и предоставит в каждой подписке, даже если replayubject завершен.

В коде, когда мы выдавали значения, запуская next в строках 17, 18, мы получим эти значения, напечатанные в строке 16, но для объекта subject или behaviorubject в строке 19 мы получим только 4, поскольку они дают только последнее значение, но в replaysubject мы получаем все предыдущие значения, сохраненные в теме воспроизведения.

Операторы

До сих пор варианты использования, которые мы использовали, были довольно простыми, но в случае реального времени нам, возможно, придется изменить или манипулировать значениями, которые мы получаем из наблюдаемого. Вот загвоздка: если мы хотим, чтобы ценность наблюдаемого объекта была выше, мы должны подписаться на него, и после подписки ваш наблюдаемый объект теряется. Затем нам нужно снова обернуть это значение в наблюдаемое и вернуть. О, черт возьми, это слишком сложно и подвержено ошибкам из-за той же проблемы, что и у нас есть операторы, которые манипулируют наблюдаемым выводом и снова обертывают его в самом новом наблюдаемом.

Операторы похожи на швейцарский нож для наблюдаемых

брать

В приведенном выше коде мы используем оператор take, который является одним из самых упрощенных операторов. Здесь наш наблюдаемый будет выдавать следующее число через каждую 1 секунду (благодаря интервальному способу создания наблюдаемого), но take займет только первые 5, а затем остановится, иначе ваш браузер рано или поздно выйдет из строя.

карта

Теперь настало время для моего самого любимого оператора - карты. Если вы когда-нибудь работали с Array.prototype.map, это почти так. За исключением того, что он отображает каждое испускаемое значение наблюдаемого вместо элементов массива и переносит это управляемое значение в новый наблюдаемый.

фильтр

Фильтр снова почти такой же, как у Array.prototype.filter, за исключением того, что он выдает только те значения, которые проходят через функцию фильтра, переданную в операторе фильтра.

В приведенном выше коде мы получим только те значения в нашей подписке, которые являются четными, что и делает оператор фильтра.

карта слияния

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

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

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

карта переключателей

Может быть случай, когда вам нужны оба значения, но вы не хотите запускать observable для каждого из них. Вариант использования: когда вы ищете строку в базе данных, но в то же время вы изменили строку. В этом случае вам нужно отменить старый запрос и запустить новый. Использование точно такое же, как и mergemap, за исключением отмены предыдущего запроса.

Вывод

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