取消基于有效负载的可观察性而不是效果

时间:2018-02-02 03:12:50

标签: angular typescript rxjs observable ngrx

我有一个服务,它向后端发出http请求我无法控制获取营销页面内容。有时,我需要同时加载多个营销内容。我可以创建一个调用服务的效果。

@Effect()
marketingContent$ = this.actions$
  .ofType(LOAD_MARKETING_CONTENT)
  .switchMap(({ payload }) => this.marketingService.getContent(payload)
    .map(content => Action.LoadMarketingContentComplete(content))
  )

这很好用,我可以拨打store.dispatch(Action.LoadMarketingContent('A'))

问题在于,如果我需要一次加载多个营销内容,.switchMap将取消之前的请求。

store.dispatch(Action.LoadMarketingContent('A'));
store.dispatch(Action.LoadMarketingContent('B'));
// Only `'B'` is loaded since 'A' gets canceled before it completes

我可以使用.mergeMap代替.switchMap,但不会取消重复请求。

我还可以使用单独的操作来加载每个营销内容,但这需要为每个部分创建一个动作和效果。

我是否可以使用.switchMap仅取消对相同内容的请求(payload相同?)或另一种同时发出不同请求的方式,同时取消重复请求同一条流?

2 个答案:

答案 0 :(得分:5)

如果您引入了CANCEL_MARKETING_CONTENT行动,则可以使用mergeMap执行此类操作:

@Effect()
marketingContent$ = this.actions$
  .ofType(LOAD_MARKETING_CONTENT)
  .mergeMap(({ payload }) => this.marketingService
    .getContent(payload)
    .map(content => Action.LoadMarketingContentComplete(content))
    .takeUntil(this.actions$.ofType(CANCEL_MARKETING_CONTENT))
  );

基本上,这可以让您根据需要加载任意数量的营销内容,但是在您发送CANCEL_MARKETING_CONTENT之前,您可以通过调度LOAD_MARKETING_CONTENT操作来取消任何待处理的加载动作(一个或多个)。

例如,要仅加载作品A,您可以执行以下操作:

store.dispatch(Action.CancelMarketingContent());
store.dispatch(Action.LoadMarketingContent('A'));

要加载AB这两个部分,您可以这样做:

store.dispatch(Action.CancelMarketingContent());
store.dispatch(Action.LoadMarketingContent('A'));
store.dispatch(Action.LoadMarketingContent('B'));

实际上,有一种相似但更整洁的方式,并且不涉及使用其他行动。

您可以使用与取消触发器相同的有效负载调度相同的操作。例如:

@Effect()
marketingContent$ = this.actions$
  .ofType(LOAD_MARKETING_CONTENT)
  .mergeMap(({ payload }) => this.marketingService
    .getContent(payload)
    .map(content => Action.LoadMarketingContentComplete(content))
    .takeUntil(this.actions$
      .ofType(LOAD_MARKETING_CONTENT)
      .skip(1)
      .filter(({ payload: next }) => next === payload)
    )
  );

从内存中,需要skip来跳过效果当前正在处理的操作。答案假设payload"A""B"等。

答案 1 :(得分:0)

您可以更改效果以检索群组中的营销内容,并仍然利用switchMap取消后续请求,而不是专门取消效果。

@Effect()
marketingContent$ = this.actions$
  .ofType(LOAD_MARKETING_CONTENT)
  .switchMap(({ payload }) => forkJoin(
    payload.map(name => this.marketingService.getContent(payload))
  ).map(content => Action.LoadMarketingContentComplete(content))

在这种情况下,payload将是要检索的内容名称数组,而不是允许您将内容作为组加载的单个名称。