Как отправить и дождаться переменного количества действий? - PullRequest
1 голос
/ 20 мая 2019

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

  • API списка команд возвращает массив идентификаторов команд.
  • API списка членов команды принимает идентификатор команды и возвращает массив идентификаторов членов команды.
  • API списка статистики принимает список идентификаторов членов команды и возвращает массив статистики.

Когда приложение запускается, я:

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

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

Вот с чем я сейчас работаю:

// actions
const TEAM_LIST = 'TEAM_LIST';
const TEAM_LIST_SUCCESS = 'TEAM_LIST_SUCCESS';
const TEAM_MEMBER_LIST = 'TEAM_MEMBER_LIST';
const TEAM_MEMBER_LIST_SUCCESS = 'TEAM_MEMBER_LIST_SUCCESS';
const STATS_LIST = 'STATS_LIST';
const STATS_LIST_SUCCESS = 'STATS_SUCCESS';

// action creators
const teamList = () => ({ type: TEAM_LIST });
const teamListSuccess = (teamIds) => ({ type: TEAM_LIST_SUCCESS, teamIds });
const teamMemberList = (teamId) => ({ type: TEAM_MEMBER_LIST, teamId });
const teamMemberListSuccess = (teamId, teamMemberIds) => ({ type: TEAM_MEMBER_LIST_SUCCESS, teamId, teamMemberIds });
const statsList = (teamMemberIds) => ({ type: STATS_LIST, teamMemberIds });
const statsListSuccess = (stats) => ({ type: STATS_LIST_SUCCESS, teamMemberIds, stats });

// epic
const fetchAllStats = (action$) => {
  return action$.ofType(TEAM_LIST_SUCCESS)
    .switchMap((action) => {
      return concat(
        action.teamIds.map(teamMemberList),
        zip(action$.ofType(TEAM_MEMBER_LIST_SUCCESS)
          .take(action.teamIds.length)
        ).map(statsList)
      )
    });
};

Я определенно неправильно использую комбинацию zip / take, потому что получаю действие STATS_LIST для каждого отправленного действия TEAM_MEMBER_LIST_SUCCESS.

Как я могу изменить это, чтобы отправлять действие statsList с результатом всех успешных действий со списком членов команды?

1 Ответ

1 голос
/ 21 мая 2019

Я думаю, что forkJoin будет соответствовать вашему сценарию Вы можете передать ему массив внутренних наблюдаемых (по одному для каждого из TEAM_MEMBER_LIST_SUCCESS действий, которые вы хотите), он будет излучать только после того, как все они завершены, и вы получите массив всех TEAM_MEMBER_LIST_SUCCESS действий, которые он захватывает.

const fetchAllStats = action$ => action$.pipe(
  ofType(TEAM_LIST_SUCCESS),
  switchMap(action => merge(
    from(action.teamIds.map(teamMemberList)),
    forkJoin(...action.teamIds.map(teamId => action$.pipe(
      filter(action => action.type === TEAM_MEMBER_LIST_SUCCESS && action.teamId === teamId),
      first(),
    ))).pipe(
      mergeMap(actions => actions.map(action => action.teamMemberIds).map(statsList)),
    ),
  )),
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...