如何分派并等待可变数量的动作?

时间:2019-05-20 20:17:22

标签: angular redux rxjs rxjs6 redux-observable

我有一个应用程序,该应用程序显示有关当前用户所属的所有团队的团队成员的统计信息表。

  • 团队列表api返回一组团队ID。
  • 团队成员列表api接受一个团队ID,并返回一组团队成员ID。
  • 统计信息列表api接受团队成员ID的 list 并返回一系列统计信息。

应用启动时,我:

  • 调度一个操作以获取用户的团队列表。
  • 成功提取团队列表时,我想调度一个操作来获取每个团队的团队成员列表。
  • 成功获取每个团队的团队成员时,我想调度带有所有团队ID的统计信息列表操作。

对于收到的每个团队ID,我都没有派遣团队成员列表操作的麻烦,但是我似乎无法“等待”所有团队成员列表成功操作来调度统计信息操作。

到目前为止,我正在与之合作:

// 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组合,因为我为发出的每个TEAM_MEMBER_LIST_SUCCESS动作获取了STATS_LIST动作。

我该如何修改此结果以分派statsList操作以及所有团队成员列表成功操作的结果?

1 个答案:

答案 0 :(得分:1)

我认为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)),
    ),
  )),
)