Последовательность действий с redux-observable

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

Я использую Redux и управляю побочными эффектами с помощью redux-observable. Вот поток с соответствующими действиями, которые я отправляю.

  • Щелчок кнопки запускает действие FIND_OR_CREATE_USER. Побочный эффект должен обрабатывать следующие шаги.
  • Найдите пользователя в бэкэнде API — отправьте GET_USER_BY_ID_REQUEST с параметром userId, побочный эффект выполнит HTTP-вызов.
  • Получить пользователя - отправить GET_USER_BY_ID_SUCCESS, ответ сохраняется в состоянии.
  • Если этот ответ пуст, создайте пользователя с CREATE_USER_REQUEST.

Теперь единственное, что этот GET_USER_BY_ID_SUCCESS также используется где-то еще в приложении (например, для получения профиля пользователя). Поэтому я не могу прослушать GET_USER_BY_ID_SUCCESS и создать пользователя сразу после него, если ответ пуст. Создайте пользователя, только если у нас есть GET_USER_BY_ID_SUCCESS, который следует за FIND_OR_CREATE_USER.

Вот как я бы сделал это с редукционными сагами:

function* findOrCreateUserSaga() {
  yield put({ type: 'GET_USER_BY_ID_REQUEST', payload: userId });
  yield take('GET_USER_BY_ID_SUCCESS');
  const response = yield select((state) => state.user);
  if (!response) {
    yield put({ type: 'CREATE_USER' }, payload: someObject );
  }
}

...

yield takeLatest('FIND_OR_CREATE_USER', findOrCreateUserSaga)

Как я могу реализовать тот же поток реактивным способом с наблюдаемым с редуксом?


person jeanpaul62    schedule 16.08.2017    source источник


Ответы (1)


Вы можете создавать новые подписки на поток action$ в любой момент эпика. Это позволяет вам динамически запускать/останавливать прослушивание определенных действий в ответ на другие действия, рабочие процессы и т. д.

Вот пример саги, переведенный на RxJS 6 (с использованием каналов) и избыточно-наблюдаемый 1+ (с использованием потока state$). Он использует функцию merge для создания наблюдаемого объекта, который одновременно выдает «GET_USER_BY_ID_REQUEST» и прослушивает «GET_USER_BY_ID_SUCCESS». Кроме того, оператор first, используемый во внутреннем канале потока action$, приводит к его завершению, когда происходит соответствующее действие.

const epic = (action$, state$) => action$.pipe(
  ofType('FIND_OR_CREATE_USER'),
  switchMap(action =>
    merge(
      of({ type: 'GET_USER_BY_ID_REQUEST', payload: userId }),
      action$.pipe(
        ofType('GET_USER_BY_ID_SUCCESS'),
        first(),
        withLatestFrom(state$),
        mergeMap(([action, state]) =>
          state.user
            ? empty()
            : of({ type: 'CREATE_USER', payload: someObject })
        ),
      ),
    )
  ),
)

В примере саги не указано, как создаются переменные userId и someObject. Обратите внимание, что то же самое верно и для приведенного выше эпического примера. Тем не менее, должно быть достаточно легко заполнить эти пробелы в зависимости от вашего конкретного варианта использования.

person seniorquico    schedule 08.06.2019