如何分派和等待可变数量的动作?
How to dispatch and wait for a variable number of actions?
我有一个应用可以显示 table 当前用户所属团队的团队成员统计数据。
- 团队列表 api returns 一组团队 ID。
- 团队成员列表 api 接受团队 ID 和 returns 团队成员 ID 数组。
- 统计列表 api 接受团队成员 ID 的 列表 和 returns 一组统计数据。
应用程序启动时,我:
- 调度一个操作来获取用户的团队列表。
- 当获取团队列表成功时,我想调度一个操作来获取每个团队的团队成员列表。
- 当成功获取每个团队的团队成员时,我想发送包含所有团队 ID 的统计列表操作。
我在为收到的每个团队 ID 发送团队成员列表操作时没有遇到任何麻烦,但我似乎无法 'wait for' 所有团队成员列表成功操作来发送统计信息操作。
这是我目前正在处理的内容:
// 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 操作?
我认为 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)),
),
)),
)
我有一个应用可以显示 table 当前用户所属团队的团队成员统计数据。
- 团队列表 api returns 一组团队 ID。
- 团队成员列表 api 接受团队 ID 和 returns 团队成员 ID 数组。
- 统计列表 api 接受团队成员 ID 的 列表 和 returns 一组统计数据。
应用程序启动时,我:
- 调度一个操作来获取用户的团队列表。
- 当获取团队列表成功时,我想调度一个操作来获取每个团队的团队成员列表。
- 当成功获取每个团队的团队成员时,我想发送包含所有团队 ID 的统计列表操作。
我在为收到的每个团队 ID 发送团队成员列表操作时没有遇到任何麻烦,但我似乎无法 'wait for' 所有团队成员列表成功操作来发送统计信息操作。
这是我目前正在处理的内容:
// 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 操作?
我认为 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)),
),
)),
)