Home > front end >  Performing multiple API calls before dispatching an Action an NgRx Effect
Performing multiple API calls before dispatching an Action an NgRx Effect

Time:11-30

I'm using NgRx @Effect and for some effect I need to perform 2 API calls: the result of the first one is used in the second one and the I want to dispatch an Action with the 2nd API call as payload this way :

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

Using a double switchMap like this I can't access action.id so I think my operators orchestration is not correct !

CodePudding user response:

Just do this in pipe inside:

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

CodePudding user response:

Maybe you need a new function, which will call getContext(), but will return what you need. Something like :

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

Then

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

You can also edit you current function getContext() in order to return the given action.

CodePudding user response:

Here is the solution that I found using concatMap operator :

@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);
                        })
                    )
            )
        );
    }
  • Related