Навіщо використовувати Redux-Oservable над Redux-Saga?


133

Я використав Redux-Saga . Код, написаний ним, поки що легко міркувати, за винятком того, що функція генератора JS час від часу псує мою голову. Наскільки я розумію, Redux-Oservable може досягти аналогічної роботи, яка справляється з побічними ефектами, але без використання функції генератора.

Однак документи з Redux-Observable не дають багато думок, чому він вищий від Redux-Saga. Я хотів би знати, чи не використання функції генератора є єдиною перевагою використання Redux-Observable. І які можуть бути недоліки, гатчі або компроміси від використання Redux-Observable замість Redux-Saga? Заздалегідь спасибі.


Я зробив веселий, але детальний блог, де я виявив, що Redux-Saga перевершує Redux-Observable для людей, які не живуть / не їдять / дихають спостереженнями цілий день. Я впевнений, що це чудово, якщо весь твій стек можна спостерігати. shift.infinite.red/…
Gant

Відповіді:


236

Відмова: Я є одним із авторів спостережувальних редукцій, тому мені важко бути 100% неупередженою.

Наразі ми не наводимо жодної причини, яку можна спостерігати за редуксом - це краще, ніж редукс-сага, оскільки ... це не так. 😆

tl; dr є плюси і мінуси для обох. Багато хто знайде один інтуїтивніший, ніж інший, але обидва є складними для вивчення різними способами, якщо ви не знаєте RxJS (можна спостерігати за редукцією) або генераторів / "ефектів як даних" (redux-saga).

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

спостережуваний за редуксом відкладає майже все на ідіоматичний RxJS. Отже, якщо ви володієте знаннями RxJS (або здобуваєте їх), навчання та використання спостережуваних за редуксом надзвичайно природно. Це також означає, що ці знання можуть бути передані іншим, ніж редукція. Якщо ви вирішили перейти на MobX, якщо ви вирішите перейти на Angular2, якщо ви вирішите перейти на якусь майбутню гарячість X, велика ймовірність, що RxJS може вам допомогти. Це тому, що RxJS - це загальна бібліотека асинхронізації, і багато в чому схожа на мову програмування - цілу парадигму "Реактивне програмування". RxJS існує з 2012 року і розпочався як порт Rx.NET (є "порти" майже на всіх основних мовах, це корисно ).

redux-saga надає свої оператори на основі часу, тому хоча знання, які ви отримуєте про генератори та обробку побічних ефектів у цьому стилі керування процесами, можна передати, фактичні оператори та використання не використовуються ні в якій іншій великій бібліотеці. Тож це трохи прикро, але, безумовно, не повинно бути самим собою укладенням угод.

Він також використовує "ефекти як дані" ( описано тут ), що спочатку може бути важко обернути головою, але це означає, що ваш код редук-саги насправді не виконує самих побічних ефектів. Натомість допоміжні функції, які ви використовуєте, створюють об'єкти, подібні до завдань, що представляють собою намір зробити побічний ефект, а потім внутрішня бібліотека виконує це за вас. Це робить тестування надзвичайно простим, без необхідності глузування та дуже привабливим для деяких людей. Однак я особисто виявив, що це означає, що ваші тести повторно реалізують велику частину логіки вашої саги - роблячи ці тести не дуже корисними ІМО (такої думки не всі поділяють)

Люди часто запитують, чому ми не робимо щось подібне зі спостережуваним редуксом: для мене це принципово несумісне з нормальним ідіоматичним Rx. У Rx ми використовуємо такі оператори, .debounceTime()які інкапсулює логіку, необхідну для дебютації, але це означає, що якщо ми хотіли зробити її версію, яка насправді не виконує розгортання, а замість цього випускає об'єкти завдань з наміром, ви втратили потужність Rx, тому що ви більше не можете просто ланцюжок операторів, тому що вони будуть працювати над цим об'єктом завдання, а не реальним результатом операції. Це справді важко пояснити елегантно. Це знову ж таки вимагає чіткого розуміння Rx, щоб зрозуміти несумісність підходів. Якщо ви дійсно хочете чогось подібного, перегляньте редукційні циклиякий використовує cycl.js і в основному має ці цілі. Я вважаю, що це вимагає занадто великої церемонії для моїх смаків, але я закликаю вас закрутити її, якщо це вас зацікавить.

Як згадував ThorbenA, я не цураюся того, щоб визнати, що редукс-сага в даний час (13.10.16) є чітким лідером у комплексному управлінні побічними ефектами для редукса. Вона була розпочата раніше і має більш міцну спільноту. Тож існує велика привабливість використання стандарту де-факто над новою дитиною на блоці. Я думаю, що це можна сміливо сказати, якщо ви використовуєте будь-який без попереднього знання, ви заплуталися. Ми обидва використовуємо досить прогресивні концепції, які, як тільки ви "отримуєте", значно ускладнюють управління побічними ефектами, але до цього багато спотикаються.

Найважливіша порада, яку я можу дати, - це не приносити жодної з цих бібліотек, перш ніж вони вам знадобляться. Якщо ви робите лише прості дзвінки Ajax, вони, ймовірно, не потребують. redux-thunk дурно простий у навчанні та забезпечує достатню кількість основ - але чим складніша асинхронізація, тим важче (а то й неможливо) це стає для redux-thunk. Але для редукційного / спостережуваного / саги багато в чому це яскраво виглядає найбільш складним є асинхроніка. У цьому ж проекті є багато заслуг у використанні редук-тунк з одним із інших (редукційне спостереження / сага)! redux-thunk для ваших звичайних простих речей, а потім лише з використанням редукційного / спостережуваного / саги для складних матеріалів. Це чудовий спосіб залишатися продуктивними, тому ви не боретесь відслідковуваного / саги за речі, які були б тривіальними за допомогою редук-тунку.


3
Просто побачила вашу розмову (uuhf звук!), І негайно натисніть ⌘ + T + "redux-saga vs redux-opable". Я використовую редукс-сагу вже досить давно (особливо в React Native), але після того, як я переглянув вашу розмову та цей пост, я можу побачити деякі випадки використання (для мене), де redux-obs. насправді було б краще підходити. Ваш приклад про debounceTime()те, що я "втратив" контроль над дуже загальною логікою, зробив це для мене. Дякуємо за пояснення.
Hulvej

3
Тільки що побачив розмову також та зробив трохи більше googling навколо. Хороший матеріал @jayphelps, дякую за обмін. Мені особливо подобається ваш коментар щодо використання redux-thunk у поєднанні з редукційним спостереженням / сагою. Це має багато сенсу, чому надскладні прості запити AJAX, коли це непотрібно. Але це означає, що можна сказати про рівномірність та підтримку людей у ​​послідовності. Знову дякую!
Спец

Перш ніж оновити до redux-saga / redux-спостерігаемого, ви можете спробувати послухати redux-dispatch-listener, який дуже простий і вже може вирішити деякі ваші користувальницькі випадки
Sebastien Lorber

Це була дуже корисна відповідь. Дякую! Мені подобається, що можна передати знання про RxJS в інші сфери / рамки.
Анселан

@jayphelps Що може бути прикладом "складної асинхронізації". В даний час, намагаючись оцінити, наскільки я повинен перейти з грона на сагу / спостереження для проекту. Дякую :)
Сем Бокай

64

Я думаю, що є речі, які потрібно враховувати.

  1. Складність
  2. Стиль кодування
  3. Крива навчання
  4. Заповітність

Скажімо, ми хочемо отримати користувача з API

// Redux-Saga

import axios from 'axios' 

function* watchSaga(){
  yield takeEvery('fetch_user', fetchUser) // waiting for action (fetch_user)
}

function* fetchUser(action){
    try {
        yield put({type:'fetch_user_ing'})
        const response = yield call(axios.get,'/api/users/1')
        yield put({type:'fetch_user_done',user:response.data})
  } catch (error) {
        yield put({type:'fetch_user_error',error})
  }
}

// Redux-Observable
import axios from 'axios'

const fetchUserEpic = action$ => 
    action$
        .ofType('fetch_user')
        .flatMap(()=>
          Observable.from(axios.get('/api/users/1')) // or use Observable.ajax
            .map(response=>({type:'fetch_user_done', user:response.data}))
            .catch(error => Observable.of({type:'fetch_user_error',error}))
            .startWith({type:'fetch_user_ing'})
        )

Також я написав цю статтю, щоб порівняти різницю між Redux-saga та Redux-Observable по глибині. Ознайомтесь з цим посиланням тут або презентацією .


3
це побічне порівняння за посиланням чудове, спасибі
rofrol

1
Мені подобається порівняння, АЛЕ в ньому є проблема, яку я хочу підняти. Коли ви порівнюєте їх за допомогою api-дзвінків, ви використовуєте функцію отримання для спостереження за редукцією. круто. АЛЕ, коли ви показуєте "скасовувані" відмінності .. ви НЕ використовуєте отримання, а замість цього використовуєте внутрішній Observable.ajax ... чому? Я вважаю за краще тримати його за допомогою "fetch" або "axios". інакше велика робота там.
Джеймс Еманон

5
@jamesemanon Я припускаю, що він не використовує завантаження, тому що API API не має можливості скасувати. (докладніше про це: github.com/whatwg/fetch/isissue/27 )
Даніель Андрій

Нічого собі, що поглиблене порівняння з усіма прикладами є найкращим. Дякую!
Радек Матей

22

Я використовую Redux-Observable над Redux-Saga, оскільки вважаю за краще працювати з спостережуваними над генераторами. Я використовую його з RXJS, яка є потужною бібліотекою для роботи з потоками даних. Подумайте про це як лодаш для асинхронізації. З точки зору будь-яких недоліків, хитрості та компромісів у виборі один за одним, погляньте на цю відповідь від Джея Фелпса:

Редукс-сага як проект існував довше, ніж редукційно-спостережливий, тому це, безумовно, одна з основних точок продажу Ви знайдете більше документації, прикладів і, ймовірно, будете мати кращу спільноту для отримання підтримки.

Протилежним є те, що оператори та API, яких ви дізнаєтесь у redux-saga, не є настільки переносними, як вивчення RxJS, який використовується повсюдно. Спостерігати за редуксом - це супер супер супер просто внутрішньо, це справді просто дає вам природний спосіб використовувати RxJS. Тож якщо ви знаєте RxJS (або хочете), це надзвичайно природне пристосування.

Наразі для більшості людей моя порада полягає в тому, що якщо вам доведеться запитати, який саме вам слід використовувати, ви, ймовірно, повинні вибрати редук-сагу.


9

Redux-Observable - це дивовижна бібліотека, ми використовуємо її у виробництві протягом 1,5 років без жодних проблем, вона ідеально перевірена і може бути легко інтегрована в будь-яку структуру. У нас надзвичайно перевантажені паралельні канали розеток, і єдине, що рятує нас від замерзань - це Redux-помітний

У мене є 3 бали, які я хотів би тут зазначити.

1. Крива складності та навчання

Тут редукс-сага легко перемагає редукцію. Якщо вам потрібен лише простий запит, щоб зробити авторизацію, і ви не хочете користуватися redux-thunk з якихось причин, вам слід розглянути можливість використання redux-saga, це просто зрозуміти.

Якщо ви не маєте попередніх знань щодо спостережуваного, це буде болем для вас, і ваша команда буде вас курсувати :)

2. Що мені можуть запропонувати спостережувані та RxJS?

Що стосується логіки асинхронізації, що спостерігається - це ваш швейцарський ніж, спостерігаючий може буквально зробити для вас майже все. Ніколи не слід порівнювати їх із обіцянками чи генераторами, це набагато потужніше, це те саме, що порівняти Optimus Prime із Chevrolet.

А як щодо RxJS? Це як lodash.js, але для логіки асинхронізації, коли ви в ній ніколи не переходите на щось інше.

3. Реактивне продовження

Просто перевірте це посилання

http://reactivex.io/languages.html

Реактивне розширення реалізовано для всіх сучасних мов програмування, це лише ваш ключ до функціонального програмування.

Тож витрачайте свій час з розумом, вивчайте RxJS та використовуйте редукційне спостереження :)


7

Я ціную переносимість у різних мовах та програмах, що мають Rx. Навіть якщо ваш додаток не змінить мови, ваша кар’єра може. Отримайте найкращі можливості для навчання, однак залежно від себе. Це такий чудовий шлюз для .Net LINQ зокрема.


2
Розумний вибір, хоча генератори теж є агностичними.
Грег Гербович

3

Оскільки тут є ціла купа розмов, що можна спостерігати за редуксом, я б подумав, що я дам сагічну сторону аргументу. Я не використовую редукційне спостереження або RxJS, тому не можу порівнювати порівняння, але я застосував саги з великим ефектом.

Для чого це варто, я використовую саги для виробництва у веб-додатку.

Сагас проти Тунка

Сага виграє руки вниз. Мені не сподобалося, як загроза вкладає логіку в мої дії творців. Це також зробило виконання кількох запитів поспіль клопіткою. Я коротко подивився на редукційне спостереження за цією роботою, але зупинився на Сагасі.

Крива навчання сагів

Розуміння, що таке генератори та чому вони важливі, є ключовим для розуміння саг. Але наголошу, що вам не потрібно знати генераторів всередині та зовні. Вам потрібно лише знати, що ви передаєте контроль із заявою про вихід і що сага передасть управління назад після того, як ваш код асинхронізації буде вирішений. Після цього трохи не дуже важко зрозуміти, що відбувається в сазі.

Основними методами саги є (на мій досвід):

  • call- Зателефонуйте до будь-якого біта коду і отримайте повернене значення. Підтримує обіцянки. Велика синергія між асинхронною обробкою та сагами.
  • select- Зателефонуйте селектору. Цей шматочок досить геніальний. Селектори є основними для скорочення, і вони підтримуються на 100%!
  • put- ака dispatchакція. Насправді відправляйте стільки, скільки вам потрібно!

Є й інші функції, але якщо ти зможеш освоїти ці три, ти опинишся у справді хорошому місці.

Висновок

Причиною, що я вибрав саги, була простота використання. спостережуване за редуксом виглядало як виклик. Я на 100% задоволений сагами. Більш щасливий, ніж я коли-небудь очікував.

На мій досвід, Саги (до речі) краще, ніж громовідводки, і порівняно їх легко зрозуміти. Rx - це не кожна чашка чаю. Я б настійно вважав, що саги замість редукційних спостерігаються, якщо ви не походите з цієї екосистеми та / або не плануєте використовувати Rx у майбутньому.


2

Якщо ви пишете заявку на Typescript, рекомендую перевірити тип . Вона натхненна Redux-Observable, а також залежить від RxJS, але для створення програми є ціла екосистема.

Найбільші мінуси редукційного спостереження / редукс-саги - відсутність настанов. Не існує офіційних вказівок про те, як ліниво зменшити навантаження, саги чи епоси. Розбиття коду є критичним для масштабування великих додатків. Спеціальні рішення для ледачого завантаження зазвичай не працюють з HMR, викликаючи поганий досвід розробника.

Безцінні плюси:

  1. Розроблено для TypeScript
    Усі API розроблені для машинопису та безпеки типу:
    • Typescript підвищить вашу продуктивність, а не сповільнить.
    • Потрібні лише необхідні примітки: аргументи стану, дії.
    • Немає набору даних. Все робиться автоматично. 95% коду виглядає як чистий JavaScript.
    • Немає RootAction, RootEpic, RootState чи інших помічників.
  2. Надайте всі будівельні блоки
    • Безхарактерне включає все для створення додатків середнього або корпоративного рівня.
    • Вам не потрібно покладатися на кілька невеликих бібліотек.
  3. Модульність
    • Належна модульність є критичною для створення масштабованих програм.
    • Немає необхідності створювати кореневі файли для епічних файлів, редукторів, типів тощо. Після створення нового модуля ви можете приєднати його з будь-якого місця. Подібно до стандартних компонентів React.
  4. Оглядний
    • Усі випадки звичайного використання та проблеми вирішуються за замовчуванням. Не потрібно надмірно думати, як виправити банальні проблеми.
    • Всі рекомендації та найкращий досвід надані!

Перевірте https://typeless.js.org/


1
Вам слід додати відмову від відповідальності, рекомендуючи програмне забезпечення, для якого ви є основним учасником.
Hagelt18
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.