[Перевод] Что такое RxJS и почему о нём полезно знать
В этом материале мы поделимся с вами переводом интервью с руководителем проекта RxJS 5+, инженером Google Беном Лешем.
В огромном мире фронтенд-разработки существует множество интересных инструментов. Я стремлюсь найти правильный подход к изучению практических вещей, поэтому я решила пообщаться с одним из самых ярких представителей RxJS-сообщества, Беном Лешем. Мне хотелось побольше узнать о RxJS, и о том, почему мне, начинающему разработчику, стоит вложить время в изучение реактивного программирования. Кроме того, мне хотелось понять — зачем применять RxJS в моих проектах. Бен рассказал мне о том, как использовать RxJS и поделился советами, касающимися изучения этой технологии.
Какую проблему решает RxJS?
Программирование — это всегда решение проблем и поиск инструментов, подходящих для поиска ответов на конкретные вопросы. В случае RxJS решаемая задача заключается в возможности обрабатывать асинхронные вызовы с помощью множества событий. На этом стоит остановиться подробнее.
Представьте, что вы пишете функцию, которая производит с данными некую последовательность действий и в ходе этой работы возникает ошибка. Если вы просто используете функции для обработки последовательностей запросов, тут могут быть некоторые необязательные действия, предпринимаемые для возврата ошибки. Вместо того, чтобы передавать ошибку через все функции, нужно иметь возможность взять ошибку и обновить представление без необходимости проходить по всем Ajax-запросам, которые теперь не нужны.
Вы можете заметить, что для организации обработки ошибок в таком стиле созданы промисы, но RxJS выводит концепцию работы с последовательными действиями на новый уровень. Промис может обрабатывать лишь единственное значение, что ограничивает варианты использования данной конструкции. В дополнение к этому, промис нельзя отменить, что означает, что он вполне может заблокировать поток и впустую использовать ресурсы (важное соображение для маломощных устройств).
В противоположность этому, RxJS даёт способ устранения этих ограничений, давая несколько каналов связи, что упрощает обработку многошаговых событий и повышает её эффективность. RxJS, кроме того, даёт разработчику возможность единообразно представлять всё, что нуждается в генерировании событий. Когда всё выглядит одинаково, оказывается, что со всем этим очень просто работать: комбинировать, объединять, выполнять запросы. Всё это делает RxJS очень мощным инструментом.
Зачем изучать RxJS?
С одной стороны, RxJS — это мощный инструмент, который позволяет превращать сложные последовательности действий в лаконичный код, с которым легко работать.
С другой стороны, эта простота основывается на множестве языковых механизмов, а их изучение требует времени. Однако, полученные знания стоят затраченных усилий, когда понимаешь, что с помощью одной строки кода можно сделать что-то вроде реализации механизма «перетащить и опустить», что требует трёх наборов событий.
Подобное даёт возможность связать эти события воедино (нажатие кнопки мыши, перемещение мыши, отпускание кнопки) для того, чтобы получить одну краткую и точную строку кода. При обычном подходе подобное требует программы в несколько десятков строк.
Какие преимущества даёт использование RxJS?
Одна из наиболее привлекательных возможностей, открывающихся при интеграции RxJS в код, заключается в том, что чем больше вы этим пользуетесь, тем больше вы сможете с помощью этой технологии сделать. RxJS можно сравнить с конструктором Lego, в том смысле, что Lego отлично подходит для разработки новых конструкций, так как все кубики имеют одинаковую форму. Похожим образом, все наблюдаемые объекты выглядят одинаково, поэтому создание чего-то с их использованием становится увлекательной задачей, так как вы можете экспериментировать со множеством интересных решений. Чем больше некто использует наблюдаемые объекты в коде, тем больше возможностей получает в создании чего-то нового на основе существующих структур.
Как выглядит процесс интеграции наблюдаемых объектов в большую кодовую базу?
Наблюдаемые объекты можно использовать практически в любом приложении. Если речь идёт о командной разработке, это может занять некоторое время, однако, переход можно упростить, если выполняются следующие условия:
- Работа начинается с применения наблюдаемых объектов, которые просты и целесообразны;
- Изменения хорошо комментируются;
- До каждого члена команды доносят смысл выполняемых действий;
Каждый осваивает подобные вещи в собственном темпе, но, в итоге, не удивляйтесь, если обнаружите, что ваша команда делает всё с помощью Rx. Когда для выполнения неких действий применяются наблюдаемые объекты, все они выглядят одинаково и их гораздо интереснее использовать, когда в приложении оказывается всё больше подобных объектов.
Существуют ли ситуации, в которых использование наблюдаемых объектов не рекомендуется?
Конечно существуют! Если перед нами отдельное событие, которое выполняет какое-то одно действие, как часто бывает в JS-программировании, тогда использовать RxJS — это малость странновато. Конечно, и тут можно применить RxJS, но это будет явный перебор.
Реализация операции «перетащить и опустить» — отличный пример задачи, для решения которой идеально подходит RxJS. Это — событие со множеством действий, сложность которого, при наличии такой возможности, всегда полезно уменьшить.
Как понять, когда следует использовать наблюдаемые объекты?
Полезно, при принятии решения о том, стоит ли использовать наблюдаемые объекты, опираться на контекст. Например:
- Если некое действие вызывает несколько событий — используйте RxJS;
- Если имеется множество асинхронных операций и вы пытаетесь наладить их совместную работу — тут тоже пригодится RxJS;
- Если вы обрабатываете огромные наборы данных в массивах и вам нужно организовать пошаговую обработку этих данных, вы можете использовать операторы RxJS как нечто вроде трансдьюсеров, когда они обрабатывают эти наборы данных без создания промежуточных массивов, которые потом придётся уничтожать с помощью сборщика мусора.
С чего стоит начать, приняв решение изучить операторы Rx?
Список операторов, с которых стоит начать, должен включать в себя map
, filter
и scan
. Среди других важных операторов можно отметить следующие:
switchMap
concat
share / shareReplay
Вы можете сузить список используемых операторов до менее чем десяти тех, которые требуются чаще всего. Есть, конечно, и операторы, с которыми можно поэкспериментировать, вроде pairwise
, bufferCount
и groupBy
. Эти таинственные операторы существуют не просто так, но пользуются ими не особенно часто. Однако, в тех редких случаях, когда вам понадобится выполнить действия, реализуемые этими операторами, вам не придётся ломать голову над тем, как создать их самостоятельно.
Легко ли начать использовать RxJS при работе с фреймворком вроде React?
Применение RxJS в React очень похоже на его применение в Angular, где он внедрён в полном объёме. В Angular наблюдаемые объекты — это полноправные сущности системы, отсюда идёт и особенная простота использования этой технологии в Angular. Однако, это не сложнее, чем подписка на RxJS в componentDidMoun
t и отписывание в componentWillUnmount
. В основе всего этого та же идея, что и в Angular, отличие только в том, что в Angular эти механизмы встроены, а в React придётся всё реализовывать вручную.
Можете ли вы поделиться какими-нибудь советами по отладке Rx?
Как и при работе с любыми другими технологиями, в ходе изучения Rx, по мере того, как накапливается опыт, упрощается и отладка. Есть некоторые ситуации, которые сложно отлаживать. Я сейчас работаю с командой разработчиков Chrome для того, чтобы решить эти проблемы.
Типичная сложная ситуация, с которой сталкиваются программисты, возникает, когда возвращают что-нибудь из mergeMap
и ожидают получить наблюдаемый объект, но оказывается, что это не наблюдаемый объект. Затем хотят получить возможность увидеть функцию, которая возвратила то, что, как они считали, должно быть наблюдаемым объектом, но им не является. В настоящее время нет способа это показать, так как нельзя узнать, что именно будет возвращено до момента возврата.
Вот несколько советов по отладке:
- Не скупитесь на вызовы
console.log()
; - Включите в цепочку наблюдаемых объектов оператор
do
, что даст возможность видеть состояние наблюдаемого объекта на разных шагах, и то, что он возвращает.
Что вы можете сказать о будущем RxJS?
В RxJS ожидается появление нескольких изменений, на которые стоит обратить внимание. Так, скоро будут доступны так называемые «арендуемые» (lettable) операторы. Благодаря этой концепции, например, вместо наличия оператора map
в самом наблюдаемом объекте, будет иметься функция map
, которая, когда её вызывают, возвращает другую функцию. Эту функцию затем будет использовать наблюдаемый объект для выполнения тех же действий, которые выполнялись с помощью его собственного оператора. Например, вместо того, чтобы писать нечто вроде observable.map.filter.scan
, можно будет написать observable.compose(map, filter, scan)
. Это — очень серьёзное и полезное изменение, так как, когда имеются функции для создания других функций — открываются множество возможностей функционального программирования. Ещё одно усовершенствование связанное с этим улучшением, заключается в устранении неиспользуемого кода при сборке пакетов (tree shaking).
В настоящее время такой оптимизации в RxJS не происходит. Всё находится в прототипах. Это даёт возможность использовать запись операторов через точку, но система не может оптимизировать размер пакета, так как весь исходный код считается используемым, даже если его, на самом деле, не применяют в конкретном проекте.
Как растущая популярность RxJS влияет React и Angular?
Надеюсь, что по мере того, как RxJS становится доступнее, и из-за того, что его всё легче интегрировать в различные проекты, он получит большее распространение в среде фронтенд-разработчиков. Сейчас широкому распространению RxJS мешают два препятствия. Первое — сложность изучения. Второе — размер библиотеки. RxJS существует уже давно, но раньше основной команде разработчиков было сложно понять то, как представить его программистам в простом и понятном виде.
Создатели Rx — замечательные люди, но они используют сложную терминологию, что привело к недостатку внимания к проекту со стороны сообщества разработчиков. Однако, благодаря образовательным ресурсам, вроде This Dot, сейчас наблюдается повышение интереса к этому замечательному инструменту.
Для того, чтобы способствовать дальнейшему распространению RxJS, сейчас я работаю над уменьшением размера библиотеки. Следите за новостями о Tiny Rx, или T-Rx. Если в двух словах, то этот проект позволил уменьшить 24-килобайтную (сжатую g-zip) библиотеку всего до 3 Кб!
Приятно наблюдать за тем, как растёт популярность RxJS, как им пользуется всё больше программистов. К тому же, надо сказать, что все желающие могут присоединиться к RxJS, внести посильный вклад в развитие этого мощного и полезного инструмента.
Если вы, немного ознакомившись с возможностями RxJS, хотите узнать больше, вот несколько полезных ссылок: Rx Workshop, Intro to Rx, Thinking Reactively и RxJS in Depth.
Уважаемые читатели! Пользуетесь ли вы RxJS в своих проектах?