在调度一个动作和 NgRx 效果之前执行多个 API 调用

Posted

技术标签:

【中文标题】在调度一个动作和 NgRx 效果之前执行多个 API 调用【英文标题】:Performing multiple API calls before dispatching an Action an NgRx Effect 【发布时间】:2022-01-06 10:36:28 【问题描述】:

我正在使用 NgRx @Effect,为了达到某些效果,我需要执行 2 个 API 调用:第一个的结果用于第二个,我想用第二个 API 调用调度 Actionpayload 这样:

@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 所以我认为我的操作员编排不正确!

【问题讨论】:

【参考方案1】:

也许你需要一个新函数,它会调用getContext(),但会返回你需要的东西。类似的东西:

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() 以返回给定的操作。

【讨论】:

很抱歉,语法上两者都不被接受:( 错误是什么? 我的 IDE 不接受语法.. 这是截图:ibb.co/cgb5MSd 看不到,如果是因为解构,我已经更新了我的帖子。 是的,这是因为破坏。但即使是第二个解决方案也不起作用......这是一个截图:prnt.sc/20zdqjy【参考方案2】:

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

@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)))
      )
  )

【讨论】:

是的,它是这样工作的!谢谢 !我找到了使用contactMap的另一种方法,我会发布它【参考方案3】:

这是我使用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);
                        )
                    )
            )
        );
    

【讨论】:

以上是关于在调度一个动作和 NgRx 效果之前执行多个 API 调用的主要内容,如果未能解决你的问题,请参考以下文章

ngrx 调度的动作未达到效果

ngrx 效果:由一个效果调度的动作是不是立即被其他效果处理?

如何同时调度多个 ngrx 动作

ngrx 8影响其他类型的调度动作

ngRx 状态更新和效果执行顺序

ngrx effect 多次调用observer,但只调度了一个action