Можно ли определить, когда эпик закончится в Redux Observable? - PullRequest
0 голосов
/ 09 мая 2019

Я новичок в RxJS, извините, если в этом нет особого смысла.

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

Упрощенный пример:

const getUserEpic = action$ =>
  action$.pipe(
    ofType(GET_USER_REQUEST),
    switchMap(action => from(service.fetchUser(action.userId).pipe(
     mapTo({ type: GET_USER_SUCCESS })))
    ),
  );

const appLoadEpic = action$ => 
 action$.pipe(
    ofType(LOAD_APP_REQUEST),
    map(() => of({ type: GET_USER_REQUEST }, { type: SOME_OTHER_REQUEST }))
  );

Что если я захочу позвонить LOAD_APP_SUCCESS после завершения всех вызванных эпосов (getUser и т. Д.)? Было бы здорово, если бы это можно было сделать в appLoadEpic, но, боюсь, это невозможно.

1 Ответ

2 голосов
/ 09 мая 2019

Способ, которым я бы предложил сделать это - объединить отдельные эпопеи в «метаэпику».То есть вы можете использовать отдельные потоки, чтобы прослушивать их отдельные события и распространять их, когда все объединенные потоки завершены.

const getUserEpic = action$ => ... 
const someOtherEpic = action$ => ...
// Creates an epic that merges all the results from each provided epic
const initializationEpic = combineEpics(getUserEpic, someOtherEpic)

const appLoadEpic = (action$, state$) => {
  // Runs the new epic with the action and state values.
  const onLoad$ = initializationEpic(action$, state$).pipe(
    endWith({type: LOAD_APP_SUCCESS})
  )

  // Listen for the load app request before subscribing to the initialization
  action$.pipe(
    ofType(LOAD_APP_REQUEST),
    mergeMapTo(onLoad$),
  )
}

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

  const appLoadEpic = (action$, state$) => {
    // Listen for the load app request before subscribing to the initialization
    action$.pipe(
      ofType(LOAD_APP_REQUEST),
      // Now the epic is injected during the app loading, and you run it inline 
      // here. This makes it easy to mock it during testing
      mergeMap(({epic}) => epic(action$, state$).pipe(endWith({type: LOAD_APP_SUCCESS}))),
    )
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...