Зачем использовать Redux-Observable вместо Redux-Saga?

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

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


person Ivan Wang    schedule 13.10.2016    source источник
comment
Я вел забавный, но подробный блог, в котором я обнаружил, что Redux-Saga превосходит Redux-Observable для людей, которые не живут / не едят / не дышат наблюдаемыми объектами весь день. Я уверен, что это здорово, если весь ваш стек является наблюдаемым. shift.infinite.red/   -  person Gant Laborde    schedule 20.08.2017


Ответы (7)


Отказ от ответственности: я являюсь одним из авторов redux-observable, поэтому мне сложно быть на 100% беспристрастным.

В настоящее время мы не приводим никаких причин, по которым redux-observable лучше, чем redux-saga, потому что ... это не так. ????

tl; dr у обоих есть плюсы и минусы. Многие найдут один более интуитивно понятным, чем другой, но оба сложны для изучения по-разному, если вы не знаете RxJS (redux-observable) или генераторы / «эффекты как данные» (redux-saga).

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

redux-observable почти все передает идиоматическому RxJS. Так что, если у вас есть знания RxJS (или вы их приобрели), изучение и использование redux-observable - это супер-суперестественно. Это также означает, что эти знания могут быть перенесены на другие вещи, кроме редукции. Если вы решите переключиться на MobX, если вы решите переключиться на Angular2, если вы решите переключиться на некоторую будущую популярность X, очень велики шансы, что RxJS может вам помочь. Это потому, что RxJS является универсальной асинхронной библиотекой и во многом похож на язык программирования сам по себе - вся парадигма «реактивного программирования». RxJS существовал с 2012 года и начинался как порт Rx.NET («порты» есть почти во всех основных языках, это очень полезно).

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

Он также использует «эффекты как данные» (описанные здесь), которые могут поначалу будет сложно осмыслить, но это означает, что ваш код redux-saga на самом деле не вызывает побочных эффектов сам. Вместо этого вспомогательные функции, которые вы используете, создают объекты, похожие на задачи, которые представляют намерение вызвать побочный эффект, а затем внутренняя библиотека выполняет это за вас. Это делает тестирование чрезвычайно простым, без насмешек и очень привлекательным для некоторых людей. Однако я лично обнаружил, что это означает, что ваши модульные тесты переопределяют большую часть логики вашей саги, что делает эти тесты не очень полезными IMO (это мнение разделяют не все)

Люди часто спрашивают, почему мы не делаем что-то подобное с помощью redux-observable: для меня это принципиально несовместимо с обычным идиоматическим Rx. В Rx мы используем такие операторы, как .debounceTime(), которые инкапсулируют логику, необходимую для устранения дребезга, но это означает, что если бы мы хотели создать его версию, которая фактически не выполняет устранение дребезга, а вместо этого испускает объекты задачи с намерением, вы теперь потеряли мощь Rx, потому что вы больше не можете просто связывать операторы, потому что они будут работать с этим объектом задачи, а не с реальным результатом операции. Это действительно сложно объяснить элегантно. Это снова требует глубокого понимания Rx, чтобы понять несовместимость подходов. Если вы действительно хотите что-то подобное, посмотрите redux-cycle, который использует cycle.js и в основном преследует эти цели. Я считаю, что это требует слишком много церемоний, на мой вкус, но я рекомендую вам попробовать, если это вас интересует.

Как упоминал ThorbenA, я не уклоняюсь от признания, что redux-saga в настоящее время (13.10.16) является явным лидером в управлении сложными побочными эффектами для redux. Он был запущен раньше и имеет более сильное сообщество. Так что использование стандарта де-факто по сравнению с новичком в округе очень привлекательно. Я думаю, можно с уверенностью сказать, что если вы используете любой из них без предварительного знания, у вас возникнет некоторая путаница. Мы оба используем довольно продвинутые концепции, которые, как только вы «поймете», значительно упрощают комплексное управление побочными эффектами, но до тех пор многие спотыкаются.

Самый важный совет, который я могу дать, - не приносить ни одну из этих библиотек до того, как они вам понадобятся. Если вы делаете только простые вызовы ajax, они вам, вероятно, не нужны. redux-thunk глупо, прост в изучении и предоставляет достаточно для основ - но чем сложнее асинхронный, тем сложнее (или даже невозможно) он становится для redux-thunk. Но для redux-observable / saga во многих отношениях он лучше всего проявляет себя, чем сложнее асинхронный режим. Также есть много достоинств в использовании redux-thunk с одним из других (redux-observable / saga) в том же проекте! redux-thunk для ваших обычных простых вещей, а затем только с помощью redux-observable / saga для сложных вещей. Это отличный способ оставаться продуктивным, поэтому вы не боретесь с redux-observable / saga из-за вещей, которые были бы тривиальными с помощью redux-thunk.

person jayphelps    schedule 13.10.2016
comment
Просто посмотрел ваш доклад (звук!) И сразу же нажал ⌘ + T + redux-saga vs redux-observable. Я уже довольно давно использую redux-saga (особенно в React Native), но после просмотра вашего выступления и этого поста я могу увидеть некоторые варианты использования (для меня), когда redux-obs. на самом деле было бы лучше. Ваш пример о debounceTime() и потере контроля над очень общей логикой произвел на меня впечатление. Спасибо за объяснение. - person Hulvej; 10.05.2017
comment
Просто посмотрел разговор и немного погуглил. Хороший материал @jayphelps, спасибо, что поделились. Мне особенно нравится ваш комментарий об использовании redux-thunk в сочетании с redux-observable / saga. В этом есть смысл, зачем усложнять простые запросы AJAX, когда в них нет необходимости. Тем не менее, есть что сказать о единообразии и поддержании единообразия людей. Спасибо еще раз! - person Spets; 03.07.2017
comment
Перед обновлением до redux-saga / redux-observable вы можете попробовать redux-dispatch-listener, который очень прост и уже может решить некоторые из ваших сценариев использования: github.com/slorber/redux-dispatch-subscribe - person Sebastien Lorber; 19.10.2017
comment
Это был очень полезный ответ. Спасибо! Мне нравится возможность передавать знания о RxJS в другие домены / фреймворки. - person Anselan; 05.01.2018
comment
@jayphelps Что было бы примером сложной асинхронности. В настоящее время я пытаюсь оценить, должен ли я переключиться с thunk на saga / observables для проекта. Спасибо :) - person Sam Bokai; 29.09.2018
comment
В файле Readme Redux-Observable в GitHub должна быть ссылка на этот ответ. - person Michael Freidgeim; 06.10.2019

Думаю, есть вещи, которые нужно учитывать.

  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. Просмотрите эту ссылку здесь или презентация.

person Wayne Chiu    schedule 13.01.2017
comment
это параллельное сравнение по ссылке отличное, спасибо - person rofrol; 01.03.2017
comment
Мне нравится это сравнение, НО есть проблема, которую я хочу затронуть. Когда вы сравниваете их с помощью вызовов api - вы используете fetch для redux-observable. Круто. НО, когда вы показываете отменяемые различия ... вы НЕ используете выборку - вместо этого вы используете внутренний Observable.ajax ... почему? Я бы предпочел использовать fetch или axios. в остальном там отличная работа. - person james emanon; 25.04.2017
comment
@jamesemanon Я предполагаю, что он не использует fetch, потому что у fetch API еще нет возможности отменить. (подробнее об этом: github.com/whatwg/fetch/issues/27) - person Daniel Andrei; 16.08.2017
comment
Вау, это подробное сравнение со всеми примерами - лучшее. Спасибо! - person Radek Matěj; 17.12.2019

Я использую Redux-Observable вместо Redux-Saga, потому что предпочитаю работать с наблюдаемыми, а не с генераторами. Я использую его с RXJS, мощной библиотекой для работы с потоками данных. Думайте об этом как о lodash для async. Что касается недостатков, ошибок и компромиссов при выборе одного по сравнению с другим, ознакомьтесь с этим ответом Джея Фелпса:

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

Счетчик в том, что операторы и API, которые вы изучаете в redux-saga, не так легко переносимы, как изучение RxJS, который используется повсеместно. redux-observable - это супер супер супер просто внутренне, это действительно просто дает вам естественный способ использования RxJS. Так что, если вы знаете RxJS (или хотите знать), это очень естественно.

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

person ThorbenA    schedule 13.10.2016

Redux-Observable - потрясающая библиотека, мы используем ее в продакшене уже 1,5 года без каких-либо проблем, она отлично тестируется и может быть легко интегрирована с любым фреймворком. У нас сильно перегружены параллельные каналы сокетов, и единственное, что спасает нас от зависаний, - это Redux-Observable.

У меня есть 3 момента, которые я хотел бы здесь упомянуть.

1. Сложность и кривая обучения

Redux-saga легко превосходит redux-observable здесь. Если вам нужен только простой запрос для выполнения авторизации, и вы по каким-то причинам не хотите использовать redux-thunk, вам следует подумать об использовании redux-saga, это просто легче понять.

Если у вас нет предварительных знаний о Observable, вам будет больно, и ваша команда обучит вас :)

2. Что могут мне предложить Observable и RxJS?

Когда дело доходит до асинхронной логики, Observable - ваш швейцарский нож, Observable может сделать за вас буквально все. Никогда не сравнивайте их с обещаниями или генераторами, он намного мощнее, это то же самое, что сравнивать Оптимус Прайм с Шевроле.

А что насчет RxJS? Это похоже на lodash.js, но для асинхронной логики, как только вы войдете, вы никогда не переключитесь на что-то другое.

3. Реактивное расширение

Просто проверьте эту ссылку

http://reactivex.io/languages.html

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

Так что потратьте свое время с умом на изучение RxJS и используйте redux-observable :)

person Denis Rybalka    schedule 25.01.2018

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

person Dean Radcliffe    schedule 20.04.2017
comment
Разумный выбор, хотя генераторы тоже не зависят от языка. - person Greg Herbowicz; 03.11.2017

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

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

Саги против Thunk

Сага безоговорочно побеждает. Мне не понравилось, как thunk вложил логику в моих создателей действий. Это также затрудняло выполнение нескольких запросов подряд. Я вкратце посмотрел на redux-observable для этой работы, но остановился на Sagas.

Кривая обучения сагам

Понимание того, что такое генераторы и почему они важны, является ключом к пониманию саг. Но подчеркну, что вам не нужно знать генераторы от и до. Вам нужно только знать, что вы передаете управление с помощью оператора yield, и что сага вернет управление после разрешения вашего асинхронного кода. После этого не очень сложно понять, что происходит в саге.

Основные методы саги (по моему опыту):

  • call - вызвать любой бит кода и получить возвращаемое значение. Поддерживает обещания. Отличная синергия между асинхронной обработкой и сагами.
  • select - Вызвать селектор. Этот бит довольно гениальный. Селекторы являются ядром redux, и они поддерживаются на 100%!
  • put - иначе dispatch действие. Фактически отправляйте столько, сколько хотите!

Есть и другие функции, но если вы овладеете этими тремя, вы окажетесь в действительно хорошем состоянии.

Заключение

Причина, по которой я выбрал саги, заключалась в простоте использования. redux-observable выглядел как проблема. Сагами доволен на 100%. Счастливее, чем я ожидал.

По моему опыту, саги (намного) лучше, чем переходы, и относительно просты для понимания. Rx - это чашка чая не для всех. Я бы настоятельно рассмотрел саги, а не наблюдаемые редукции, если вы не из этой экосистемы и / или не планируете использовать Rx в будущем.

person Julius Ecker    schedule 05.02.2019

Если вы пишете свое приложение на Typescript, я рекомендую выбрать без типа. Он вдохновлен Redux-Observable, а также зависит от RxJS, но есть целая экосистема для создания приложения.

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

Бестиповые плюсы:

  1. Designed for TypeScript
    All APIs are designed for typescript and type-safety:
    • Typescript will boost your productivity, not slows you down.
    • Требуются только необходимые аннотации: состояние, аргументы действия.
    • Без приведения типов. Все делается автоматически. 95% кода выглядит как чистый javascript.
    • Нет RootAction, RootEpic, RootState или других вспомогательных типов.
  2. Provide all building blocks
    • Typeless includes everything to build mid-sized or enterprise level apps.
    • Вам не нужно полагаться на несколько небольших библиотек.
  3. Modularity
    • Proper modularity is critical for building scalable apps.
    • Нет необходимости создавать корневые файлы для эпиков, редукторов, типов и т. Д. Создав новый модуль, вы можете прикрепить его из любого места. Аналогичен стандартным компонентам React.
  4. Opinionated
    • All common use cases and problems are solved by default. No need to over-think how to fix trivial issues.
    • Предоставляются все рекомендации и лучшие практики!

Ознакомьтесь с https://typeless.js.org/

person sky    schedule 06.10.2019
comment
Вы должны добавить отказ от ответственности, рекомендуя программное обеспечение, для которого вы являетесь основным разработчиком. - person Hagelt18; 06.02.2020