How can I best use rxjs to perform multiple fetch operations in a single action using a forEach approach

0 votes

I am new to React and tasked with modifying an existing application which already performs multiple api calls. The pattern that is in use in the app is demonstrated by the below example. EG if an action mapperActions.selectPolygon of type CaseReducerActions<CaseReducers> is raised, then the below code will execute, calling the fetchPolygon function to retrieve data asynchronously from an AWS lambda and the returned result will be processed by the fetchPolygonCompleted function.

let fetchPolygonStatsEpic = (action$: any, state$: StateObservable<RootState>) => action$.pipe(
  ofType(
    mapperActions.selectPolygon.type,
    mapperActions.alterQueryIndexname.type,
  ),
  filter(()  => state$.value.mapper.selectedPolygon !== undefined),
  switchMap(() =>
    concat(
      of(globalActions.startLoading('polygon')),
      fetchPolygon(state$.value.mapper).pipe(
        map(result => mapperActions.fetchPolygonCompleted(result)),
        catchError(e => of(globalActions.errorOccurred(e.message)))),
      of(globalActions.stopLoading('polygon')),
    )
  )
)

The change I need to implement is as follows:

I have a type 'Framework'...

export type Framework = {
....
}

...a collection of these...

export const frameworks: {[framework: string]: Framework} = {
  liveng0: {
    ...
  },
  liveng1: {
    ...
  },
  habmosCairngorms: {
    ...
  },
  spaceintCairngorms: {
    ...
  }
}

..and an API method that retrieves data for a specified Framework...

export let fetchHabitats = (requiredFramework: Framework): Observable<FrameworkHabitats> => {
...
}

When the action mapperActions.initialise of type CaseReducerActions<CaseReducers> is raised, I need to execute a block of code which will execute and process 4 separate asynchronous API calls to fetch the data for each of the 4 framework types above in turn.

A naive approach of simply copy-and-pasting the API call for each framework in turn within the app's establised pattern for fetching data actually works correctly and produces the results I require, ie:

let fetchHabitatsEpic = (action$: any, state$: StateObservable<RootState>) => action$.pipe(
  ofType(
    mapperActions.initialise.type,
  ),
  switchMap(() =>
    concat(
      of(globalActions.startLoading('habitats')),
      fetchHabitats(frameworks.liveng0).pipe(
        map(result => mapperActions.fetchHabitatsCompleted(result)),
        catchError(e => of(globalActions.errorOccurred(e.message)))),
      fetchHabitats(frameworks.liveng1).pipe(
        map(result => mapperActions.fetchHabitatsCompleted(result)),
        catchError(e => of(globalActions.errorOccurred(e.message)))),
      fetchHabitats(frameworks.habmosCairngorms).pipe(
        map(result => mapperActions.fetchHabitatsCompleted(result)),
        catchError(e => of(globalActions.errorOccurred(e.message)))),
      fetchHabitats(frameworks.spaceintCairngorms).pipe(
        map(result => mapperActions.fetchHabitatsCompleted(result)),
        catchError(e => of(globalActions.errorOccurred(e.message)))),        
      of(globalActions.stopLoading('habitats')),
    )
  )
)

Although the above works as required, it clearly needs to be replaced with a forEach approach that operates over each Framework in turn and treats each API call atomically, whilst still being able to trigger all 4 from a single action. Could you please explain the syntax required to achieve this?

Jan 9, 2023 in AWS by Ashwini
• 5,430 points

edited 5 days ago 11 views

No answer to this question. Be the first to respond.

Your answer

Your name to display (optional):
Privacy: Your email address will only be used for sending these notifications.
webinar REGISTER FOR FREE WEBINAR X
REGISTER NOW
webinar_success Thank you for registering Join Edureka Meetup community for 100+ Free Webinars each month JOIN MEETUP GROUP