Как заставить redux-observable отправлять несколько действий до и после запроса ajax?

Я пытаюсь написать Epic для наблюдаемого сокращения. Но у меня проблема (

ON_EMPTY_FORM_STATE действие выполняется до выполнения .map(response => formSavedAction(response)).

Как я могу это исправить? В основном я пытаюсь получить:

  1. Захватить FORM_SEND действие
  2. Отправить запрос Ajax с полезной нагрузкой
  3. Если я получу ответ 200 от сервера, выполните formSavedAction(response)
  4. Если я получаю ошибку 500, отправьте { type: ON_FORM_SUBMIT_ERROR }
  5. В конце (независимо от того, какой запрос Ajax был возвращен) я хочу отправить действие { type: EMPTY_FORM_STATE }

А вот мой код:

const saveProductEpic = (action$, $store) =>
action$.ofType(SUBMIT_FORM)
    .mergeMap(action => ajax.post('http://localhost:9000/products', action.payload,
        { 'Content-Type': 'application/json' }))
    .map(response => formSavedAction(response))
    .catch(err => { $store.dispatch({ type: ON_FORM_SUBMIT_ERROR }) })
    .do(() => { $store.dispatch({ type: EMPTY_FORM_STATE }) })

Проблема в том, что действие { type: EMPTY_FORM_STATE } отправляется до, а не после запроса AJAX.

Есть ли способ исправить это?


person user2397623    schedule 28.08.2017    source источник
comment
просто удалите блок .do и добавьте $store.dispatch({ type: EMPTY_FORM_STATE }) к двум случаям .then и .catch   -  person Amr Aly    schedule 28.08.2017
comment
Не работает .... Я получаю ошибку TypeError: action $ .ofType (...). MergeMap (...). Map (...). Then is not a function   -  person user2397623    schedule 29.08.2017
comment
могу я узнать, почему вы используете .map вместо .then в своем коде? а какую http библиотеку вы используете?   -  person Amr Aly    schedule 29.08.2017
comment
Будет ли какая-то разница, если я буду использовать .then вместо .map? Я использую RX.Dom.Ajax   -  person user2397623    schedule 29.08.2017


Ответы (2)


Принцип работы redux-observable заключается в том, что наблюдаемое, возвращаемое эпической функцией, подписывается в промежуточном программном обеспечении. Ваш наблюдаемый объект должен испускать действия redux, потому что функция подписки просто: action => store.dispatch(action)

Поскольку вы напрямую используете store.dispatch в своем эпике, вы обходите наблюдаемый redux и отправляете вещи не в том порядке, который вы ожидаете.

Чтобы выполнить действия в ожидаемом порядке, вы можете сделать это:

action$.ofType(SUBMIT_FORM)
  .mergeMap(action => ajax.post('http://localhost:9000/products', action.payload,
    { 'Content-Type': 'application/json' }))
  .map(response => formSavedAction(response))
  // Notice that catch is now returning the value by dropping the brackets.
  .catch(err => Observable.of({ type: ON_FORM_SUBMIT_ERROR }))
  // send whatever action has come through, and add the empty state action after it.
  .mergeMap(action => Observable.of(action, { type: EMPTY_FORM_STATE }))

Демонстрация концепции: https://jsbin.com/focujikuse/edit?js,console

person meticoeus    schedule 28.08.2017
comment
Да - пожалуйста, не используйте store.dispatch github.com/redux -observable / redux-observable / issues / 314 - person jayphelps; 29.08.2017
comment
Я пытался сделать эпопею по-вашему, но происходит что-то странное ... Похоже, что actions .map (response = ›formSavedAction (response)) и mergeMap (action =› Rx.Observable.from (action $, {type: ON_EMPTY_FORM_STATE})) вообще никогда не выполняются ... Я добавил запись в свой редьюсер, и он абсолютно ничего не показывает. - person user2397623; 29.08.2017
comment
Исправлена ​​ошибка в последней mergeMap; нужно использовать, а не из. Попробуйте войти в эпос с операторами .do (console.log). Если он не проходит мимо запроса ajax, вероятно, проблема в этом. - person meticoeus; 29.08.2017

const saveProductEpic = (action$, $store) => action$.ofType(SUBMIT_FORM) .mergeMap(action => ajax.post('http://localhost:9000/products',action.payload, { 'Content-Type': 'application/json' }) .mergeMap(response => Observable.of(formSavedAction(response), emptyFormStateAction())) .catch(err => Observable.of( formSubmitErrorAction(), emptyFormStateAction()) ) );

где emptyFormStateAction и formSubmitErrorAction - это создатели действий.

person bitsthatmatter    schedule 09.02.2018