NGRX 效果中的 concatLatestFrom 循环
concatLatestFrom loop inside NGRX effect
我有 orders/order 个项目,它们被组织在 schedules/schedule 个项目中。每个订单项目对应1+个计划项目。
我有一个功能可以让用户批准(或不批准)一个计划项目,这也会导致与同一订单项目相关的所有其他计划项目得到批准。批准一个项目可能会导致相应的计划被重新排序。
在实际将计划项目设置为已批准之前,我需要进行时间戳检查以确保用户正在处理最新数据。一般的工作流程是将所有 'affected entities' 与相应的 http 请求一起传递。
我现在正在努力的是在我的影响范围内从 NGRX 存储中获取所有受影响的实体,特别是我需要获取
- 与输入项在同一计划中的所有计划项
- 与输入项具有相同顺序项的所有计划项 ('split items')
- 与那些拆分项目在同一计划中的所有计划项目
- 所有相应的时间表
我有这些选择器:
export const getScheduleById = (id: number) =>
createSelector(getScheduleEntities, (entities) => entities[id]);
export const getScheduleItemsForSchedule = (scheduleId: number) =>
createSelector(getScheduleItemsAlls, (all) => all.filter(x => x.id === scheduleId));
export const getOtherSchedulesForOrderItem = (scheduleItem) =>
createSelector(getScheduleItemsAlls, (all) => all.filter(x => x.orderItemId === scheduleItem.orderItemId));
我的(不完整的)效果看起来像这样(已批准:布尔值):
approveItem$ = createEffect(() =>
this.actions$.pipe(
ofType(scheduleItemActions.approveItem),
concatMap(({ item, approved }) =>
of({ item, approved }).pipe(
concatLatestFrom(() => [
this.store.select(scheduleItemSelectors.getOtherSchedulesForOrderItem(item)),
this.store.select(scheduleSelectors.getScheduleById(item.scheduleId)),
this.store.select(scheduleItemSelectors.getScheduleItemsForSchedule(item.scheduleId))
]),
// At this point I would need to do a concatLatestFrom store.select with 'getScheduleById'
// and 'getScheduleItemsForSchedule' for all 'splitItems', but I don't know how to that.
// Subsequent map etc. has to be adjusted of course:
// I'd combine down to ({ item, approved, allSchedules*, allScheduleItems* })
// *Separated since right know I distinguish 'object type' in code, not by property and interfaces only exist during dev time.
map(([{ item, approved }, splitItems, itemSchedule, itemScheduleItems]) =>
({ item, approved, splitItems, itemSchedule, itemScheduleItems })
)
)
),
switchMap(({ item, approved, splitItems, itemSchedule, itemScheduleItems }) => {
let affectedEntities: AffectedEntity[] = /* just builds a list with subset-information of the entities (object type, id, timestamp) */
return this.scheduleItemService.approveItem(item, approved, affectedEntities).pipe(...);
})
)
);
我对 rxjs 运算符还不太熟悉,这个让我很难过。
非常感谢帮助 and/or 涵盖类似内容的资源(我找不到任何东西,但我也不知道有什么好的关键字来搜索这个)。
因此,根据评论,我将逻辑移至单独的选择器。
现在看起来有点像:
选择器:
export const getApproveAllSchedules = (item: ScheduleItem) =>
createSelector(
getScheduleAll,
scheduleItemSelectors.getScheduleItemsForOrderItem(item.orderItemId),
(all, splitItems) => {
let scheduleIds = splitItems.map((o) => o.scheduleId);
return all.filter((x) => scheduleIds.indexOf(x.id) > -1);
}
);
//---
export const getApproveAllScheduleItems = (item: ScheduleItem) =>
createSelector(
getScheduleItemAll,
getScheduleItemsForOrderItem(item.orderItemId),
(all, splitItems) => {
let schedules = splitItems.map((o) => o.scheduleId);
return all.filter((x) => schedules.indexOf(x.id) > -1);
}
);
效果:
approveItem$ = createEffect(() =>
this.actions$.pipe(
ofType(scheduleItemActions.approveItem),
concatLatestFrom(({ item, approved }) => [
this.store.select(scheduleSelectors.getApproveAllSchedules(item)),
this.store.select(scheduleItemSelectors.getApproveAllScheduleItems(item)),
]),
switchMap(([{ item, approved }, schedules, scheduleItems]) => {
let affectedEntities: AffectedEntity[] = /* just builds a list with subset-information of the entities (object type, id, timestamp) */
return this.scheduleItemService.approveItem(item, approved, affectedEntities).pipe(...);
})
)
);
我有 orders/order 个项目,它们被组织在 schedules/schedule 个项目中。每个订单项目对应1+个计划项目。
我有一个功能可以让用户批准(或不批准)一个计划项目,这也会导致与同一订单项目相关的所有其他计划项目得到批准。批准一个项目可能会导致相应的计划被重新排序。
在实际将计划项目设置为已批准之前,我需要进行时间戳检查以确保用户正在处理最新数据。一般的工作流程是将所有 'affected entities' 与相应的 http 请求一起传递。
我现在正在努力的是在我的影响范围内从 NGRX 存储中获取所有受影响的实体,特别是我需要获取
- 与输入项在同一计划中的所有计划项
- 与输入项具有相同顺序项的所有计划项 ('split items')
- 与那些拆分项目在同一计划中的所有计划项目
- 所有相应的时间表
我有这些选择器:
export const getScheduleById = (id: number) =>
createSelector(getScheduleEntities, (entities) => entities[id]);
export const getScheduleItemsForSchedule = (scheduleId: number) =>
createSelector(getScheduleItemsAlls, (all) => all.filter(x => x.id === scheduleId));
export const getOtherSchedulesForOrderItem = (scheduleItem) =>
createSelector(getScheduleItemsAlls, (all) => all.filter(x => x.orderItemId === scheduleItem.orderItemId));
我的(不完整的)效果看起来像这样(已批准:布尔值):
approveItem$ = createEffect(() =>
this.actions$.pipe(
ofType(scheduleItemActions.approveItem),
concatMap(({ item, approved }) =>
of({ item, approved }).pipe(
concatLatestFrom(() => [
this.store.select(scheduleItemSelectors.getOtherSchedulesForOrderItem(item)),
this.store.select(scheduleSelectors.getScheduleById(item.scheduleId)),
this.store.select(scheduleItemSelectors.getScheduleItemsForSchedule(item.scheduleId))
]),
// At this point I would need to do a concatLatestFrom store.select with 'getScheduleById'
// and 'getScheduleItemsForSchedule' for all 'splitItems', but I don't know how to that.
// Subsequent map etc. has to be adjusted of course:
// I'd combine down to ({ item, approved, allSchedules*, allScheduleItems* })
// *Separated since right know I distinguish 'object type' in code, not by property and interfaces only exist during dev time.
map(([{ item, approved }, splitItems, itemSchedule, itemScheduleItems]) =>
({ item, approved, splitItems, itemSchedule, itemScheduleItems })
)
)
),
switchMap(({ item, approved, splitItems, itemSchedule, itemScheduleItems }) => {
let affectedEntities: AffectedEntity[] = /* just builds a list with subset-information of the entities (object type, id, timestamp) */
return this.scheduleItemService.approveItem(item, approved, affectedEntities).pipe(...);
})
)
);
我对 rxjs 运算符还不太熟悉,这个让我很难过。
非常感谢帮助 and/or 涵盖类似内容的资源(我找不到任何东西,但我也不知道有什么好的关键字来搜索这个)。
因此,根据评论,我将逻辑移至单独的选择器。
现在看起来有点像:
选择器:
export const getApproveAllSchedules = (item: ScheduleItem) =>
createSelector(
getScheduleAll,
scheduleItemSelectors.getScheduleItemsForOrderItem(item.orderItemId),
(all, splitItems) => {
let scheduleIds = splitItems.map((o) => o.scheduleId);
return all.filter((x) => scheduleIds.indexOf(x.id) > -1);
}
);
//---
export const getApproveAllScheduleItems = (item: ScheduleItem) =>
createSelector(
getScheduleItemAll,
getScheduleItemsForOrderItem(item.orderItemId),
(all, splitItems) => {
let schedules = splitItems.map((o) => o.scheduleId);
return all.filter((x) => schedules.indexOf(x.id) > -1);
}
);
效果:
approveItem$ = createEffect(() =>
this.actions$.pipe(
ofType(scheduleItemActions.approveItem),
concatLatestFrom(({ item, approved }) => [
this.store.select(scheduleSelectors.getApproveAllSchedules(item)),
this.store.select(scheduleItemSelectors.getApproveAllScheduleItems(item)),
]),
switchMap(([{ item, approved }, schedules, scheduleItems]) => {
let affectedEntities: AffectedEntity[] = /* just builds a list with subset-information of the entities (object type, id, timestamp) */
return this.scheduleItemService.approveItem(item, approved, affectedEntities).pipe(...);
})
)
);