Введение в функциональное реактивное программирование в Redux

1656628690 vvedenie v funkczionalnoe reaktivnoe programmirovanie v

автор Бхуван Малик

nWV0vFKplVlN71FMMrbAftR6KaY-x9euAjzU

Начнем с того, что такое «реактивное программирование»:

Реактивное программирование это парадигма асинхронного программирования, касающаяся потоков данных и распространения конфигураций.
— Википедия

ReactiveX или Rx является самым популярным API для реактивного программирования. Он построен на идеологии наблюдаемого шаблона, шаблона итератора и функционального программирования. Rx имеет библиотеки для разных языков, но мы будем использовать RxJS.

Rx основан на Наблюдаемые, наблюдатели, и Операторы

По сути наблюдатель подписывается к Observable.

Затем Observable испускает потоки данных, которые наблюдатель прослушивает и реагирует, запуская цепочку операций над потоком данных. Реальная мощность поступает от операторов или «реактивных расширений» (отсюда термин Rx).

Операторы позволяют трансформировать, комбинировать, манипулировать и работать с последовательностью выпускаемых элементов Observables.

Если вы не знакомы с Rx, вам может быть трудно понять и использовать Redux-Observable. Поэтому я предлагаю вам сначала запачкать руки Rx!

Теперь переходим к использованию RxJS из Redux.

Redux-Observable

6oEOGaUYU93i90xMzNA6GjY1lVaohtAjHKkR

Redux-Observable – это промежуточное программное обеспечение на основе RxJS для Redux

Вот что Redux Docs должно сказать о промежуточном программном обеспечении в Redux:

Промежуточное программное обеспечение обеспечивает точку расширения третьей стороны между отправкой действия и моментом, когда оно достигает редуктора.

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

Итак, как все это делает Redux-Observable?

Из-за былин. Эпики являются главным примитивом Redux-Observable. Эпик – это простая функция, выполняющая действие, а затем возвращающая другое действие. Action In → Action Out. Поэтому действия рассматриваются как потоки.

Каждое действие, отправленное в любом компоненте React, будет проходить через такие функции (Epics) как поток.

Давайте посмотрим, что это за простой эпос action 'PING’ и возвращает a новый action 'PONG’ выглядит как:

const pingEpic = action$ =>  action$.filter(action => action.type === 'PING')    .mapTo({ type: 'PONG' })

The $ после action используется, чтобы указать, что эти переменные ссылаются на потоки. Таким образом, мы имеем поток действий, передаваемых в эпос, на котором мы использовали filter оператор RxJS.

Этот оператор фильтра отфильтровывает все действия, не относящиеся к type PING! Поэтому эпос pingEpic касается только действий по обработке type ‘PING’. Наконец, это action ‘PING’ отображается на новый action с type ‘PONG’ соответствуя главному правилу эпоса: Action In → Action Out.

Поскольку каждый эпос касается только определенного типа действия, у нас есть специальный оператор для action$(поток), чтобы отфильтровать нежелательные действия из потока. Этим оператором является ofType() оператор.

Переписка предыдущего Epic с помощью ofType мы получаем:

const pingEpic = action$ =>  action$.ofType('PING')  .mapTo({ type: 'PONG' })

Если вы хотите, чтобы ваша эпопея разрешала больше одного типа действий, то ofType() оператор может принимать любое количество аргументов, например: ofType(type1, type2, type3,...).

Знакомство с особенностями работы эпоса

Вы можете подумать, что действие PING просто появляется и поглощается этим эпосом. Это не так. Есть две вещи, которые всегда нужно помнить:

  1. Каждое действие всегда сначала идет к редуктору
  2. Лишь после этого это действие получает эпос

Поэтому цикл Redux работает нормально, как и положено.

The action ‘PING’ сначала достигает редуктора, а затем получает Epic, а затем меняется на новый action ‘PONG’ который отправляется в редуктор.

Мы даже можем получить доступ к состоянию магазина внутри Epic, поскольку второй аргумент Epic – это облегченная версия Redux Store! Смотрите ниже:
const myEpic = (action$, store) =>
Мы можем только блll store.getState() и получить доступ к состоянию внутри Epics.

Цепочка оператора

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

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

Мы получаем преимущества обратных вызовов, без того пресловутого «ада обратного звонка».

Ниже смотрите, как мы можем использовать мощность операторов.

Распространенный случай использования

Предположим, что мы хотим искать слово с помощью чего-то вроде API словаря, используя текст, введенный пользователем в режиме реального времени. В основном, мы имеем дело с хранением (в магазине Redux) и отображением результатов вызова API. Мы также хотели бы отменить вызов API, чтобы API вызывался, скажем, в течение 1 секунды после того, как пользователь перестанет вводить.

Вот как это будет сделано с помощью операторов Epic и RxJS:

const search = (action$, store) =>  action$.ofType('SEARCH')  .debounceTime(1000)  .mergeMap(action =>    ajax.getJSON(`     .map(payload => ({ type: 'SET_RESULTS', payload }))     .catch(payload => Observable.of({type: 'API_ERROR', payload}))  )

Слишком много для обработки?! Не беспокойтесь, давайте разберем это.

Эпос приобретает целый поток действий oftype ‘SEARCH’. Поскольку пользователь постоянно печатает, полезная нагрузка каждого входного действия (action.payload) содержит обновленную строку поиска.

Оператор debounceTime() используется для фильтрации некоторых действий в потоке, кроме последней. По сути он передает через него действие, только если прошла 1 секунда без получения другого действия или наблюдаемого действия.

Затем мы делаем запрос AJAX, сопоставляя результаты с другим действием 'set_RESULTS' принимающий данные ответа (payload) к редуктору, являющемуся частью Action Out.

Любые ошибки API фиксируются с помощью catch оператор. Выпускается новое действие с деталями ошибки, а затем отображается тостер с сообщением об ошибке.

Обратите внимание, как улов находится внутри mergeMap() а после запроса AJAX? Это потому, что mergeMap() создает изолированную цепь. Иначе ошибка достигнет ofType() и завершит нашу эпопею. Если это произойдет, Epic перестанет слушать какие-либо действия в будущем!

Мы также можем использовать традиционные обещания по запросам AJAX. Однако у них есть такая присущая проблема, что они не могут быть отменены. Таким образом, еще один важный вариант использования Epics – это отмена AJAX.

Мы используем takeUntil оператора для решения этой проблемы. Это делается так, как мы использовали это catch оператор внутри mergeMap и после запроса AJAX.

Это происходит потому takeUntil должно остановить текущий запрос AJAX, а не весь Epic! Поэтому изоляция цепочек операторов здесь тоже важна.

Отказ, регулировка, фильтрация, отмена AJAX и другие – это только верхушка айсберга. В нашем распоряжении множество операторов, что делает сложные случаи использования тривиальными для разрешения. Используя эти операторы, вы можете быть настолько креативными, насколько позволяет ваше воображение! Функциональное реактивное программирование (FRP) по-своему элегантно.

В этой статье я сосредоточился на части пояснения FRP в Redux с помощью Redux-Observable. Чтобы настроить Redux-Observable в React+Redux, обратитесь к официальным документам – они очень хорошо документированы, подробны и легки.

Обязательно просмотрите мою другую статью о Redux, в которой исследуются лучшие методы создания редукторов:

Уменьшение шаблона Reducer с помощью createReducer()
Во-первых, краткий итог того, что такое редукторы в Redux:medium.freecodecamp.org

Хотите улучшить свои базы JavaScript? Дайте прочесть эти:

Функции JavaScript ES6: хорошие части
ES6 предлагает несколько интересных новых функциональных функций, которые делают программирование JavaScript гораздо более гибким. Давайте поговорим о…medium.freecodecamp.orgРуководство по поднятию переменных JavaScript? с let и const
ННовым разработчикам JavaScript часто трудно понять уникальное поведение переменной/функции hoisting.medium.freecodecamp.org Функция подъема и подъема Вопросы на собеседование
Это часть 2 моей предыдущей статьи о подъеме переменных под названием «Руководство по подъему переменных JavaScript? с…мedium.freecodecamp.org

Мира ✌️

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *