在分派 Action 和 NgRx Effect 之前执行多个 API 调用

Performing multiple API calls before dispatching an Action an NgRx Effect

我正在使用 NgRx @Effect 并且为了某些效果我需要执行 2 API 调用:第一个的结果用于第二个并且我想发送一个Action 第二个 API 调用为 payload 这样:

@Effect()
FetchDetails() {
  return this.actions.pipe(
    ofType(actions.SOME_ACTION),
    switchMap((action: SomeAction) => this.myService.getContext()),
    switchMap((ctx: Context) => this.myService.fetchDetails(action.id, ctx.requesterType)
      .pipe(
        map((response: Details) => new SetDetails(response)),
        catchError(err => {return of(new SetFetchDetailsError(err))})
      )
  )
}

像这样使用双 switchMap 我无法访问 action.id 所以我认为我的运算符编排不正确!

也许您需要一个新函数,它会调用 getContext(),但会 return 您所需要的。像 :

getContextAction(action: SomeAction): Observable<any> {
  return this.getContext().pipe(
    map(ctx => { action, ctx });
}

然后

@Effect()
FetchDetails() {
return this.actions.pipe(
  // ...
  switchMap((action: SomeAction) => this.myService.getContextAction(action)),
  switchMap((value) => this.myService.fetchDetails(value.action.id, value.ctx.requesterType)
  // ...
}

您还可以编辑当前函数 getContext() 以 return 给定的操作。

只需在管道内执行此操作:

@Effect()
FetchDetails() {
  return this.actions.pipe(
    ofType(actions.SOME_ACTION),
    switchMap((action: SomeAction) => this.myService.getContext().pipe(
      switchMap((ctx: Context) => this.myService.fetchDetails(action.id, ctx.requesterType)
    ))
      .pipe(
        map((response: Details) => new SetDetails(response)),
        catchError(err => {return of(new SetFetchDetailsError(err))})
      )
  )
}

这是我使用 concatMap 运算符找到的解决方案:

@Effect()
    FetchApiDetails() {
        return this.actions.pipe(
            ofType(apis.FETCH_SELECTED_API_DETAILS),
            concatMap((action: FetchSelectedApiDetails) =>
                this.contextInit.getContext()
                    .pipe(
                        switchMap((ctx: Context) => this.apisManagementService.fetchApiDetails(action.apiId, ctx.requesterType)
                            .pipe(
                                map((response: ApiDetails) => new SetApiDetails(response)),
                                catchError(err => {
                                    return of(new SetFetchApiDetailsError(err))
                                })
                            )
                        ),
                        catchError(err => {
                            console.log('An error happened when fetching context ' + err);
                            return of(err);
                        })
                    )
            )
        );
    }