【发布时间】:2020-02-09 18:54:21
【问题描述】:
我在 Angular 应用程序中有同一个组件的多个实例。组件的每个实例都将调度一个操作[Action] LoadData 以从外部 API 加载数据。该操作的有效负载包含有关哪个组件调度该操作的信息,以便能够将其存储在store 中正确的对应位置。
无论操作中包含什么其他有效负载,每次获取的数据都是相同的。既然是这种情况,我不需要执行多个 API 调用来加载相同的数据,因此我可以使用 switchMap 取消任何以前未完成的调用。
为此我有两个作用,一个是加载数据:
@Effect({ dispatch: false })
loadData$ = this.actions$.pipe(
ofType<LoadData>(LOAD_DATA),
switchMap((action) => { // This will cancel out any previous service call
return this.service.loadData().pipe(
tap(val => {
console.log(`Loading data...`)
this.dataSubject$.next(val) // When the data is fetched, emit on the subject
})
);
})
);
一个处理与数据结合的调度动作
@Effect()
handleActionAndDataLoaded$ = combineLatest(
this.actions$.pipe(
ofType<LoadData>(LOAD_DATA)
),
this.dataSubject$.asObservable()
).pipe(
tap(_ => console.log(`All done`))
)
其中dataSubject$ 是Subject。
这对我来说是棘手的部分。如果LoadData 动作已被调度n 次,我需要触发第二个效果n 次,然后结合其他动作有效负载处理数据因此。我现在得到的是第二种效果的一个触发器。
阅读combineLatest 并查看大理石图,这当然是预期的行为。
在大理石图中我得到类似的东西
我需要的是类似下面的东西。
我知道还有其他方法可以通过更改应用程序架构中的其他内容来解决整个问题,但这是我目前必须解决的问题,在我看来这是一个有趣的rxjs 问题!
如何做到这一点?我缺少什么运算符组合?
【问题讨论】:
-
也许这在您的实际服务中最容易解决。只需在其中应用一个缓存主题并将其返回给您。通话只完成一次,您的其他要求都已满足。
-
你怎么知道
n事件已经结束了?可以在应用程序中再次触发吗?否则,当触发新的事件集时,您最终将丢失响应this.service.loadData()的任何更改。如果可能,请详细说明 -
@ShashankVivek 好问题!在我的真实代码中,它们将分批分派一次,有时会分派一次,尽管不是很频繁。此外,最多
n = 12. -
@DanielB:恕我直言,你做得不对。使用
RxJs处理这个问题不是一个好习惯。似乎更像是一种掩饰。据我记得,switchMap使用内部Observable切换值,不确定您期望之前的http调用被取消的评论。1.确认一下,我认为您的LOAD_DATA将进行 12 次 API 调用(即针对每个操作事件)2.如果您是开放的,我可以尝试在没有 Rxjs 的情况下回答,但使用更好的effect和 @987654348 @管理
标签: angular rxjs ngrx ngrx-effects