首页 > 解决方案 > 如何调度和等待可变数量的动作?

问题描述

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

当应用程序启动时,我:

对于我收到的每个团队 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 操作以及所有团队成员列表成功操作的结果?

标签: angularreduxrxjsrxjs6redux-observable

解决方案


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

推荐阅读