The State of Reactive in JS: практический обзор FRP библиотек

    Статья родилась из этого ответа на StackOverflow и переросла в этот блог пост (на английском), но я думаю она не утратила актуальность.

    Сейчас очень много шума вокруг Reactive Programming. Я потратил какое-то время на изучение этой дисциплины применимо к JavaScript и Node.js и сложил свое мнение о самых, на мой взгляд, интересных библиотеках.

    RxJS


    Это своего рода эталон – появление Reactive Extensions для .net, в каком-то смысле, создало эту дисциплину.

    Pros:



    Cons:


    • Иногда выглядит как «матан». Документации напоминают бездну – не понятно, как это все «на голову натянуть»?
    • Реализовано ребятами с Java`ой в голове (любовь к большому количеству абстракций, идиоматика из Java/.Net, иногда странные сигнатуры). Это не то чтобы плохо, просто некоторые вещи смотрятся в JS странными (пример Scheduler – я так и не понял зачем это все нужно в single-thread среде). Отсюда же желание писать на TypeScript`e

    Bacon.js


    Когда-то модная библиотека для хипстеров – сейчас все забыли

    Pros


    • Хорошая документация и хорошие примеры от комьюнити (например, игра Змейка);
    • Реализованы почти все примитивы из Rx*;
    • Реализовывали в первую очень для JS и JSсным бэкграундом;
    • ИМХО, очень легко начать просто пройдясь по примерам и документации.

    Cons


    • Нет Backpressure – давайте просто забудем про backend разработку

    Highland.js


    Библиотека от caolan – автора async

    Pros:


    • Сразу писалось для JS/Node.js ребятами которые на них писали что-то большое и любят язык/платформу – а значит JS-ная идиоматика и Node.js в голове (см. следующий пункт);
    • Построенно поверх Node.js Stream, это обеспечело библиотеке маленький размер. Кроме того, субъективно, так намного легче про это все думать: у нас есть stream A, мы с ним что-то делаем и pipe`аем его в stream B (вот моя статья, с примером);
    • backpressure – Причем насколько я понимаю ничего не нужно было писать руками, все уже есть в Node.js Stream.

    Cons:


    • Слабая документацияуже получше и отсутсвие примеров. За примерами прийдется лезть в Rx или Bacon – смиритесь с этим;
    • Отсутсвие многих примитивов. Не то чтобы их сложно реализовать руками, но все же. Пример .interval и .combineLatest;
    • Очень субъективно: Флегматичное коммьюниты – сами пишут, сами кайфуют, экспансии не ведут.

    Вместо итога


    Из-за отстутсвия вменяемых примеров вам прийдется посмотреть все эти библиотеки, Rx* так точно. ИМХО, самая правильная Highland – люди, которые ее писали, понимают идиоматику платформы и любят ее. Самая «зрелая» RxJS – ее еще в Angular «впилили», hype-гарантирован.

    Подсказка: Если вам нужно что-то спросить на StackOverflow – переводите сразу RxJS-«диалект», так с большей вероятностью ответят.
    Поделиться публикацией

    Похожие публикации

    Комментарии 16

      +3
      Все эти вещи примитивны, ничего нет как было написано (матан) и все такое. Rx это вывернутый итератор грубо говоря это (o => ({o(10); o(20)}))(x => console.log(x)) просто на это натянули классы, много шума, но если понимать это на примитивах типа функций то https://github.com/xgrommx/from-combinators-to-fp/blob/master/src/frp/reactive.js. Идея дуализма https://jsbin.com/bihoke/2/edit?html,js,console https://github.com/xgrommx/from-combinators-to-fp/blob/master/src/frp/duality.js
      В плане доки, да для 5 версии она уродская, для 4 я когда-то сделал это http://xgrommx.github.io/rx-book (когда у Rx с этим были большие проблемы)
      Bacon появился потому что автору было не понятно идея холодных, горячих, подогретых обзерваблов (хотя его идея мне тоже нравится)
      MostJs — офигенный пример как надо делать вещи нацеленные на перформанс (быстрее его пока нет) также у него идея почти полность FP принципы и не зря это расшифровывается как Monadic Streams
      Также есть интерсные вещи типа https://github.com/paldepind/flyd или https://github.com/funkia/hareactive
      https://github.com/staltz/xstream идея которого только горячие обзерваблы
      И еще много чего http://xgrommx.github.io/rx-book/content/resources/reactive_libraries/index.html#libraries
      Да и вообще обернувши Either (монаду) в асинхронную обертку можно даже такое делатьhttps://github.com/xgrommx/practical-functional-programming/blob/master/stream.js
      Я много еще чего не привел тут, ну много можно найти в моей книге (там много чего есть в разделе Resources)
      Плюс для Rx я сделал https://jsbin.com/migogu/1/edit?js,output когда надо нужно объяснить как это работает (помимо http://rxmarbles.com/)
      Еще забыл упомянуть про одну классную фичу в Bacon и частично сделанную в Rx — это join pattern (update в Bacon и в Rx это можно сделать через when)
        0
        Вот как это можно сделать в Rx https://github.com/xgrommx/react-rx-flux/blob/master/src/rx-extensions.js#L37
        Еще этот же варинт в most.js (у этой либы нет when поэтому такая версия) https://github.com/xgrommx/most-reactive-flux/blob/master/app/src/utils.js#L8 (кстати так же можно сделать в Rx)
        Еще в Rx очень много операторов могут быть выражены через малый базис https://gist.github.com/xgrommx/1aec6c7e47757799a7695ba08a9541ee
        Ну и еще для стримов нет границ :D
          +1
          Bacon появился потому что автору было не понятно идея

          ИМХО, это очень громкое утверждение – https://baconjs.github.io/api.html#for-rxjs-users, скорее у него было другое виденье вопроса

          (матан) и все такое

          тут есть три разныех момента:
          1. Документация – выглядит как справочник по матану: на тебя вываливают кучу всего и нег говорят зачем тебе это нужно и с чего начинать(e.g.: gettingstarted)
          2. Реализация – пояснил в статье свое мнение
          3. И про «монады»: не все люди по умолчанию знают что такое «монада», «дуализм», «Monadic Streams», «малый базис». Подобные объяснения отталкивают новичков. По-моему, это одна из причин почему про FRP больше говорят, чем используют

            0
            И про «монады»: не все люди по умолчанию знают что такое «монада», «дуализм», «Monadic Streams», «малый базис». Подобные объяснения отталкивают новичков. По-моему, это одна из причин почему про FRP больше говорят, чем используют

            Не то что про FRP да и FP ничего не знают — читают, но не понимают почему эту лучше?
            Нет примеров, которые бы 100% (или хоть 50%) демонстрировали, — смотрите, вот по старому, а вот по новому (FRP да и FP ) и это лучше!

            Имхо, конечно, имхо. (С)
              0

              https://habrahabr.ru/post/325320/ вот тут попытался показать пример.

                0
                https://habrahabr.ru/post/325320/ вот тут попытался показать пример.


                Хм. Нет, не уговорили. ;-)
                  0

                  Фанкторы (извиняюсь за произношениe) или композиция для улучшения читаемости кода:


                  //italian-pasta style
                  
                  function updateUrl(url) {
                    return addParam(
                      addParam(
                        removeParam(
                          updateParam(url, 'x', 1),
                          'y'
                        ),
                        'z', 2
                      ),
                      'hello', 'world'
                    );
                  }
                  
                  //vs multiple re-assignments
                  
                  function updateUrl(url) {
                    url = updateParam(url, 'x', 1);
                    url = removeParam(url, 'y');
                    url = addParam(url, 'z', 2);
                    url = addParam(url, 'hello', 'world');
                    return url;
                  }
                  
                  //vs Functor
                  
                  function updateUrl(url) {
                    return [url]
                      .map(x => updateParam(x, 'x', 1))
                      .map(x => removeParam(x, 'y'))
                      .map(x => addParam(x, 'z', 2))
                      .map(x => addParam(x, 'hello', 'world'))
                      .reduce(x => x);
                  }
                  
                  //vs Functor with curried functions
                  
                  function updateUrl(url) {
                    return [url]
                      .map(updateParam('x', 1))
                      .map(removeParam('y'))
                      .map(addParam('z', 2))
                      .map(addParam('hello', 'world'))
                      .reduce(x => x);
                  }
                  
                  //vs composition with curried functions
                  
                  const updateUrl = compose(
                    addParam('hello', 'world'),
                    addParam('z', 2),
                    removeParam('y'),
                    updateParam('x', 1)
                  );
            +1

            Так что такое эти разнотемпературные обсерваблы?

              0

              Так что такое эти разнотемпературные обсерваблы?

                0
                http://xgrommx.github.io/rx-book/content/getting_started_with_rxjs/creating_and_querying_observable_sequences/creating_and_subscribing_to_simple_observable_sequences.html#cold-vs-hot-observables
                Они еще могут быть из горячих превращены в теплые))) за счет Observable.defer
                  0

                  Как у вас там в мире стримов всё сложно..

              0

              MobX вроде тоже как FRP себя позиционирует.

                0

                Судя по видео ниже, в MobX изпользуют observables, но по коментариям от выступающей она зачислила его в OO мир а не в FP


                MobX vs Redux: Comparing the Opposing Paradigms - React Conf 2017
                  0

                  MobX — это реализация OORP.

                  0
                  kefir.js
                    +1
                    что в нем «особенного»?

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

                  Самое читаемое