Redux-observable: вызов вспомогательной функции после завершения ряда эпопей по извлечению данных - PullRequest
0 голосов
/ 28 апреля 2018

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

3 вызова API могут быть получены одновременно, однако перенаправление должно ждать, пока выборка не будет завершена. Я показал свою попытку до сих пор.

Все вызовы API работают так, как они должны, и сохраняют извлеченные данные в Redux, поэтому (я думаю) проблема в loadUserEpic, который управляет всем процессом и вызывает функцию перенаправления. Как бы мне лучше структурировать этот эпос, чтобы достичь того, чего я хочу?

import { userRedirect } from 'ui/client/helpers/userRedirect';

const loadUserEpic = action$ =>
  action$.ofType('LOAD_USER').pipe(
    mergeMap(() =>
      Observable.of(
        {
          type: 'FETCH_USER_CONFIG'
        },
        {
          type: 'FETCH_USER_MODULES'
        },
        {
          type: 'FETCH_USER_DIVISION'
        },
        userRedirect()
      )
    )
  );

const userConfigEpic = action$ =>
  action$.ofType('FETCH_USER_CONFIG').mergeMap(() =>
    fromPromise(axios.get(`/me/configuration`))
      .map(response => ({
        type: 'FETCH_USER_CONFIG_SUCCESS',
        data: response.data
      }))
      .catch(error =>
        Observable.of({
          type: 'FETCH_USER_CONFIG_ERROR',
          error
        })
      )
  );

const userModulesEpic = action$ =>
  action$.ofType('FETCH_USER_MODULES').mergeMap(() =>
    fromPromise(axios.get(`/me/modules`))
      .map(response => ({
        type: 'FETCH_USER_MODULES_SUCCESS',
        data: response.data
      }))
      .catch(error =>
        Observable.of({
          type: 'FETCH_USER_MODULES_ERROR',
          error
        })
      )
  );

const userDivisionEpic = action$ =>
  action$.ofType('FETCH_USER_DIVISION').mergeMap(() =>
    fromPromise(axios.get(`/division/`))
      .map(response => ({
        type: 'FETCH_USER_DIVISION_SUCCESS',
        data: response.data
      }))
      .catch(error =>
        Observable.of({
          type: 'FETCH_USER_DIVISION_ERROR',
          error
        })
      )
  );

1 Ответ

0 голосов
/ 28 апреля 2018

Сначала запустите все три действия для получения данных:

const loadUserEpic = action$ =>
  action$.ofType('LOAD_USER').pipe(
    mergeMap(() =>
      Observable.of(
        {
          type: 'FETCH_USER_CONFIG'
        },
        {
          type: 'FETCH_USER_MODULES'
        },
        {
          type: 'FETCH_USER_DIVISION'
        },
      )
    )
  );

Теперь дождитесь завершения каждого из выполненных действий и каким-то образом проверьте, есть ли у вас все, что вам нужно:

const redirectEpic = (action$, store) => 
  action$.ofType(
    'FETCH_USER_CONFIG_SUCCESS',
    'FETCH_USER_MODULES_SUCCESS',
    'FETCH_USER_DIVISION_SUCCESS'
  ).pipe(
    mergeMap(() => {
      const state = store.getState(); 
      const iHaveConfig = isConfigFetched(state);
      const iHaveModules = areModulesFetched(state);
      const iHaveDivisions = areDivisionsFetched(state);

      if(iHaveConfig && iHaveModules && iHaveDivisions) {
        return useRedirect();
      }

      return Observable.empty();
    })
  )
...