Введение

Эта статья принадлежит к серии под названием «Angular встречает RxJS», в которой я пытаюсь как можно лучше объяснить реактивное программирование с использованием «RxJS» в контексте «Angular».

Оглавление

Основные концепции
Субъекты RxJS
Операторы RxJS (Часть 1)
Операторы RxJS (Часть 2)
Операторы RxJS (Часть 3)
TakeUntil и async канал »
Наблюдаемые высшего порядка
Обработка ошибок
Планировщики RxJS (скоро)
Мини-проект: создание Pokedex (вскоре)

В предыдущей статье…

… Мы говорили о функциональном программировании, мраморных диаграммах и операторах создания. Мы использовали их для создания наблюдаемых из обычных значений или путем комбинирования других наблюдаемых. Теперь мы увидим другой тип операторов: конвейерные. Эти операторы используются для преобразования одного наблюдаемого в другое.

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

Трубка

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

карта

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

Здесь мы используем функцию «pipe», чтобы применить оператор «map» к исходному наблюдаемому, чтобы вернуть другой наблюдаемый, который испускает проекцию каждого значения исходного объекта. Следствием этого является то, что «subscribe» фактически вызывается для наблюдаемого вывода, а не для исходного объекта, поэтому подписка на самом деле является подпиской не на «observable $», а на наблюдаемый объект, возвращаемый функцией «pipe».

Выполнение этого кода приведет к следующему результату:

Таким образом, выполнение этого кода можно разбить на следующие этапы:

  • Наблюдаемый источник создается как диапазон от «0» до «4».
  • Другая наблюдаемая создается путем применения оператора «map» к исходной наблюдаемой.
  • Создается подписка на наблюдаемый выход.
  • Наблюдаемый источник выдает первое значение: «0».
  • Оператор «map» выполняется для этого значения и выдает прогнозируемое значение в выходной наблюдаемый объект. В этом случае функция проекции просто умножает значение на себя, поэтому результат будет «0».
  • Наблюдаемый источник выдает второе значение: «1».
  • Оператор «map» выполняется для этого значения и выдает прогнозируемое значение в выходной наблюдаемый объект. В этом случае функция проекции просто умножает значение на себя, поэтому результат будет «1».
  • И так далее…

Мраморная диаграмма этого кода следующая:

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

фильтр

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

Приведенный выше код применяет фильтр к наблюдаемому источнику, чтобы сохранить только те значения, которые можно разделить на «2». Результат этого кода:

Мраморная диаграмма этого кода следующая:

Также возможно получить индекс текущего значения, используя второй параметр функции, переданной в «filter»:

Операторы цепочки

До сих пор мы использовали операторы один за другим, но сила «RxJS» - это возможность связывать операторы в цепочку. Например, мы могли бы объединить два оператора, которые мы только что видели, чтобы отфильтровать значения и сопоставить те, которые прошли тест:

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

Кран

Оператор «касания» является наиболее простым и используется, чтобы «что-то сделать» с выдаваемыми значениями. Это очень полезный оператор для отладки наблюдаемых путем записи в консоль различных генерируемых значений. Например, мы могли бы обновить предыдущий пример, чтобы регистрировать значения сразу после оператора «filter»:

Разница между приведенным выше кодом и предыдущим заключается в том, что мы записываем отфильтрованные значения в консоль перед выполнением оператора «map».

Как видите, конечный результат тот же: «0», «4», «16», «36» и «64», однако мы также видим, что некоторые значения регистрируются (желтым цветом) при нажатии »Оператор. Это те значения, которые прошли оператор «фильтр» до того, как были спроецированы «картой».

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

брать

Оператор take берет сначала «n» значений, выдаваемых наблюдаемым источником, затем завершает выходное. Тот факт, что наблюдаемое завершено, очень важен и может использоваться, чтобы избежать сохранения подписки и отказа от подписки.

Приведенный выше код фильтрует значение диапазона, чтобы сохранить только четные единицы и берет только три первых. Еще раз, оператор take применяется к значению, испускаемому наблюдаемым, возвращаемым оператором «filter», другими словами, все значения, которые даже не учитываются оператором «take». Мы также определили «завершенный» обратный вызов, чтобы показать, что «take» завершает наблюдаемое, когда достигается количество значений, указанных в аргументе.

Мраморная диаграмма этого кода следующая:

взять

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

В этом примере оператор принимает значения, если они меньше «5». После передачи значения выше или равного «5» наблюдаемый завершается.

Вы также можете использовать второй параметр takeWhile, чтобы указать, что вы также хотите передать первое значение, не удовлетворяющее предикату. Например, если вы укажете «true» в этом параметре для приведенного выше кода, результат будет немного другим:

Мраморная диаграмма первой версии кода выглядит следующим образом:

пропускать

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

В этом примере «skip» игнорирует 5 первых выданных значений, а затем начинает выдавать другие.

skipWhile

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

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

Мраморная диаграмма выглядит следующим образом:

первый

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

В этом случае первое значение, удовлетворяющее предикату, - «6», поэтому только это значение выдается до завершения вывода наблюдаемого.

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

В этом случае, поскольку никакое значение не удовлетворяет предикату до завершения исходной наблюдаемой, выдается значение по умолчанию («0»).

Мраморная диаграмма первого примера выглядит следующим образом:

последний

Если есть «первый», есть «последний». Этот оператор просто выдает последнее значение, соответствующее условию, до завершения наблюдаемого источника.

Это даст:

Соответствующая мраморная диаграмма следующая:

DifferentUntilChanged

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

В приведенном выше коде мы создаем наблюдаемое из массива, содержащего повторяющиеся последовательные значения. Использование «independentUntilChanged» гарантирует, что два одинаковых значения никогда не будут отправлены одно за другим. Результат кода выше:

Как видите, все повторяющиеся последовательные значения, такие как [«2», «2»] или [«4», «4»], были выданы только один раз. По умолчанию этот оператор использует оператор «===» для сравнения значений, однако вы можете предоставить ему параметр, чтобы это изменить. В следующем примере сравнивается абсолютное значение значений.

В этом коде мы сравниваем значения по их абсолютному значению, поэтому значения [«2», «-2»] считаются равными.

Мраморная диаграмма первого примера выглядит следующим образом:

ownUntilKeyChanged

Этот оператор служит той же цели, что и «independentUntilChanged», за исключением того, что вы должны указать имя свойства значения. Например, вы можете использовать его, чтобы выдавать слова только в том случае, если их длина отличается:

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

Что касается «отличногоUntilChanged», вы можете использовать второй аргумент для определения функции сравнения.

Мраморная диаграмма для этого примера:

Последние мысли

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