避免使用 @ngrx/effects 来取消相同的操作

Avoid @ngrx/effects to cancel same actions

有没有办法避免影响取消前一个?

我需要做的:

this.tagsStoreService.initTagsForFamilyId(this.tagFamily.id)

我有这个效果:

@Effect() initTagsForFamilyId$: Observable<Action> = this.actions$
    .pipe(
        ofType<InitTagsForFamilyIdAction>(TagsStateActionTypes.INIT_TAGS_FOR_FAMILY_ID_ACTION),
        switchMap(params => {
            // this.loadingService.showLoading();
            return this.tagsService.initTagsForFamilyId(params.payload)
                .pipe(
                    exhaustMap((data) => {
                        this.loadingService.hideLoading();

                        return [
                            new InitTagsForFamilyIdSuccessAction({ ...data }),
                        ];
                    }),
                    catchError(error => {
                        // this.loadingService.hideLoading();
                        return of(new TagsFailureAction({ error }));
                    }),
                );
        }),
    );

在此先感谢您的帮助 ;-)

您应该使用 mergeMap 而不是 switchMap

let {
  interval,
  of
} = rxjs
let {
take,
tap,
switchMap,
delay,
finalize
} = rxjs.operators

const switchMapCase = interval(500).pipe(
  take(5),
  tap(() => console.log("new request")),
  switchMap(() =>
    of(null).pipe(
      delay(800),
      tap(() => console.log("end")),
      finalize(() => console.log("request stream complete"))
    )
  )
);

switchMapCase.subscribe();
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.6/rxjs.umd.min.js"></script>

如果您 运行 上面的代码片段(带有 switchMap 的代码片段),您会注意到每 500 毫秒都会发出一个新事件(新请求),此事件将会发生在 switchMap 和 return 内,一个新的可观察对象将在 800 毫秒后被解析,因为 800 > 500 在内部可观察对象被解析之前,新的可观察对象将会到来来自源流,这将取消当前的内部流(具有 800 毫秒延迟的流),并且将 return 编辑一个也具有 800 毫秒延迟的新流。 这件事会发生 5 次(因为 take(5) 运算符,这相当于分派 TagsStateActionTypes.INIT_TAGS_FOR_FAMILY_ID_ACTION 动作 5 次,每个 dispathc 之间有 500 毫秒延迟)。在第 5 次迭代中,内部 observable 将完成,因为不会有新的调度取消它。

let {
  interval,
  of
} = rxjs
let {
take,
tap,
mergeMap,
delay,
finalize
} = rxjs.operators

const mergeMapCase = interval(500).pipe(
  take(5),
  tap(() => console.log("new request")),
  mergeMap(() =>
    of(null).pipe(
      delay(800),
      tap(() => console.log("server response recieved")),
      finalize(() => console.log("request stream complete"))
    )
  )
);

mergeMapCase.subscribe();
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.6/rxjs.umd.min.js"></script>

在上面的代码片段(mergeMap)中,我们几乎拥有相同的结构,唯一的区别是我们使用 mergeMap 而不是 switchMap,区别在于与switchMap(取消之前的流)mergeMap 将新的“innerStream”添加到源可观察对象而不取消旧的。

*旁注:* 实际上在效果中被取消的不是 actioneffect 它是 this.tagsService.initTagsForFamilyId 可观察的,完成后将触发另一个 action.