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

Вот что написано в документации

RxJS (Reactive Extensions for JavaScript) — это библиотека для реактивного программирования, которая позволяет работать с асинхронными данными, используя Observable последовательности. RxJS предоставляет мощные операторы для создания, комбинирования и обработки потоков данных.

Давай разберемся по пунктам и начнем с того что такое асинхронные данные!

Асинхронные данные - это данные, которые мы получаем с задержкой.
Представь, что ты заказываешь пиццу по телефону. Сначала ты делаешь заказ, а потом ждёшь, пока пиццу приготовят и доставят. В это время ты можешь делать другие дела. Когда пицца готова, тебе звонят, и ты её получаешь. В программировании, когда мы запрашиваем данные, например, с сервера, мы можем сразу не получить ответ. Пока данные приходят, программа может продолжать выполнять другие задачи. Когда данные будут готовы, мы их получим и обработаем.

Пример:


Объясняю что только что произошло: Метод of принимает на вход любое количество аргументов и возвращает готовый экземпляр Observable. После подписки он испустит полученные значения и завершится. А теперь пройдемся по каждому пункту этого академического пояснения как я и обещал для самых маленьких!

1. Observable — это объект, который представляет поток данных с течением времени. Этот поток данных можно рассматривать как последовательность событий или значений, которые передаются асинхронно. Объект Observable предоставляет возможность подписаться на этот поток данных( в данном примере это "Данные получены") и получать уведомления о новых событиях или значениях.

Observables полезны для моделирования широкого спектра асинхронных источников данных, таких как пользовательский ввод, сетевые запросы и таймеры.

В RxJS Observables создаются с помощью Observableконструктора или одного из многих методов статического создания.of, from, и interval. Ими можно манипулировать с помощью широкого спектра операторов, таких какmap, filter, и mergeMap, и на них можно подписаться с помощью subscribeметода. Но обо всем по порядку.

.pipe() - Метод вызывается у объекта, а операторы передаются ему в качестве аргументов через запятую в порядке их вызова. Тоесть в нашем примере мы передали в функция pipe оператор- delay, он что-то делает с нашей строкой( об этом позже) и дальше отдает полученное значение подписчику. Этих оператором в pipe может быть много- этакая оболочка для них!

.subscribe() - Дальше идет как вы уже догадались подписка на получение данных! Проще говоря, .subscribe() используется для начала прослушивания данных, передаваемых Observable, .subscribe() метод принимает один или несколько аргументов в качестве функций обратного вызова, которые вызываются при получении новых данных. В нашем примере мы передали 1 аргумент функцию консоль лог и вывели строку "Данные получены" в консоль. Как видишь не чего сложного!

Операторы. Давай теперь поговорим немного о них, собственно ради чего это все затевалось! Приведу теперь пример по сложнее:

Прочитай внимательно код! Особенно комментарии в нем!
В итоге, через 3 секунды после запуска кода, в окне alert будет выведено сообщение "Обработка: Дополнительные данные".

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

  • Создания (offromfromEventinterval);

  • Преобразования (mapscanbuffer);

  • Фильтрации (filtertakeskipdistinct);

  • Обработки ошибок (catchErrorretryonErrorResumeNext);

  • Условия (skipUntilskipWhiletakeUntiltakeWhile);

  • Математические (minmaxcount);

  • Утилиты (tapdelay);

  • Для Connectable Observable (shareshareReplaypublish).

Так же забегая в перед для более продвинутых дядек но не совсем, хочу вставить одну важную ремарку касаемо subscribe. Про первый аргумент мы уже поговорили теперь расскажу об остальных двух - потому что это очень важно знать.
Второй аргумент (необязательный) - это функция-обработчик, которая будет вызываться в случае, если в потоке Observable произойдет ошибка. Эта функция принимает один аргумент - объект ошибки.!
Третий аргумент (необязательный) - это функция-обработчик, которая будет вызываться в конце потока Observable, когда он завершится успешно или с ошибкой.

Как видишь сложного тут не чего нет! Основная идея это сделать что-то асинхронное- в основном это запросы на сервер, потом дождаться когда данные придут к нам в тело Observable и потом вертеть этими данными как нам захочется с помощью мощной библиотеке операторов предоставляемой RxJs. Например дождался JSON файл с сервака- обработал его операторами и вывел в тимплейт клиенту. ВСЁ!

Главное по больше практики и тогда поточность будет тебе казаться детским садиком!

Вот такие пироги!

Комментарии (10)


  1. markelov69
    24.05.2024 10:58

    Жесть, вот это уродский код, просто кровь из глаз.
    async/await вам в помощь и традиционный подход к программированию, тогда и будет вам счастье.


    1. frct1
      24.05.2024 10:58

      async/await относится к другой парадигме. RxJs манипулирует потоками данных, а не однократным выполнением.


    1. IpGuru Автор
      24.05.2024 10:58
      +1

      В данной статье разобрана библиотека RxJs которая уже по умолчанию используется в Angular. Вся архитектура данного фреймворка завязана на ней! Все начинающие ангулярщики это знают и данная библиотека уже идет по дефолту к изучению с этим фреймворком. Ни кто не запрещает использовать async/await  в купе с RxJs но когда вы попадете в реальную компанию то 99% ассинхроности будет реалезовано с помощью данной библиотеке. Ну а об плюсах по сравнению с async/await  можете сами найти в паутине!


    1. FinderOT
      24.05.2024 10:58
      +1

      Тут скорее кто к чему привык и какая задача стоит, мне, например, гораздо удобнее и понятнее RxJs, нежели async/await и промисы, которые в добавок работают как некая неизбежность - они обязательно так или иначе должны выполнится, а с RxJx можно подписаться на поток когда тебе надо, так же отписаться, получать данные из потока не сразу, а с задержкой, объединять данные с нескольких потоков и ещё много чего. Да, с async/await тоже некоторые подобные штуки можно делать, но выглядеть это будет "не очень", плюс достаточно сложно для прочтения это будет.


      1. markelov69
        24.05.2024 10:58
        +1

        Тут скорее кто к чему привык и какая задача стоит, мне, например, гораздо удобнее и понятнее RxJs, нежели async/await и промисы

        Да, с async/await тоже некоторые подобные штуки можно делать, но выглядеть это будет "не очень", плюс достаточно сложно для прочтения это будет.

        А можно пожалуйста пример из реальной жизни, т.е. то, что в реальности приходится решать разработчикам фронта, хотя бы в среднем на каждом пятом проекте где именно код с RxJs будет понятней/лучше, а традиционная разработка с тем же async/await просто не решит задачу или код будет непонятным по сравнению с RxJs? Прям ссылку на codesandbox/stackblitz пришлите, а я реализую то же поведение, но традиционными методами, просто сравним код хотя бы даже ради интереса. А то всё что я всегда слышу это о каких-то магических кейсах и сценариях где Rx это пушка, но реального сценария я так никогда и не видел где он выигрывает традиционный подход. Надеюсь вы такой сценарий предоставите, главный критерий это реальный, а не вымышленный или 1 на 10000 кейс. Буду очень благодарен.


        1. snicksnk
          24.05.2024 10:58
          +1

          Чтобы дернуть один запрос с бекенда async, await достаточно, как и в 99% задач фронта. Странно говорить про технологию/методологию что она фигня, ничего в ней не понимая. Код на rx точно ни в каком виде не будет понятнее, если никогда не работал с rx.
          Это другая парадигму программирования (реактивное программирование) лично у меня он на фронте не прижился, на проектах был не только я, а порог входа там на голову выше чем async/await и я из мира реакта, а не ангуляра, где rx - дефолт.
          Но на беке активно его использовал именно для обработки потоков данных. Вообще выучил его с 0 когда мне нужно было приоритезированную очередь сделать. Могу даже код показать
          https://github.com/snicksnk/inst-observer/blob/develop/src/utils/ig-queque/request/requesSheduleFactory.ts
          Но естественно ты там ничего не поймешь.
          Еще rxjs всегда под капотом у nestjs
          Отдельная песня это тестирование марбл диаграммами, это вообще другой подход к разработке, когда ты с потоками данных работаешь, а не с императивными функциями, просто с приставкой await


          1. markelov69
            24.05.2024 10:58

            Но на беке активно его использовал именно для обработки потоков данных

            Просто абстрактно и опять 0 конкретики, а именно что тут традиционный подход не канает или код будет нечитемым.

            Вообще выучил его с 0 когда мне нужно было приоритезированную очередь сделать

            И? При чем тут rxjs если это достаточно тривиальная штука. Опять же 0 конкретики, какая-то абстрактная очередь.

            Еще rxjs всегда под капотом у nestjs

            И что теперь? А если бы там был под капотом jQuery первой версии? Или Redux?

            когда ты с потоками данных работаешь, а не с императивными функциями, просто с приставкой await

            Опять максимально абстрактные слова без конкретики и кода.

            P.S. Очередное подтверждение, что RxJs не может противопоставить традиционному подходу ничего, от слова совсем. Разве только write-only код, от которого кровь из глаз льется


  1. RuslanYestemessov
    24.05.2024 10:58
    +1

    Спасибо за статью, хороший онборд для начинающих.


    1. IpGuru Автор
      24.05.2024 10:58
      +1

      Спасибо бро)


  1. vanilla_master
    24.05.2024 10:58

    RxJs есть одна маленькая проблемка, современные генераторы (function*) делают всё тоже самое но лучше, ну вернее производительнее и точно так же не очевидно, поэтому в нем особо нет смысла