0
votes

I'm trying to dispatch multiple actions, then perform a secondary step after every initial actions have completed. I'm able to dispatch multiple actions, but am unable wait for their responses. Instead of array of response actions, I'm receiving an array a request actions. With Redux-Observables, how can I dispatch multiple actions, wait for all of them to complete, then perform a secondary step with their responses? I've tried different operators, such as forkJoin, concat, but I ultimately end up with the same issue.

interface Action1ResponseType { 
  id: string;
  name: string;
  address: Address;
  ...
}

interface Action2ResponseType { 
  id: string;
  addressId: string;
  addressValidation: AddressValidation;
  ...
}

interface Action3ResponseType { 
  id: string;
  addressId: string;
  addressHistory: AddressHistory
  ...
}

interface PageLoaded {
  viewModels: [{
    addressToInspect: { 
      id: string;
      address: Address;
      history: AddressHistory;
      validation: AddressValidation;
      ...
    }]
  }
  ...
}
import { createAction } from 'typesafe-actions';

const action1 = () => createAction('ACTION1')<Action1ResponseType[]>();
const action2 = () => createAction('ACTION2')<Action2ResponseType[]>();
const action3 = () => createAction('ACTION3')<Action3ResponseType[]>();

// Usage example:
const action1ToDispatch = action1({id: '123'});
// action1ToDispatch (the request) will be:
// {
//   type: 'ACTION1',
//   payload: {
//     id: '123'
//   }
// }
dispatch(action1ToDispatch);
Example responses:
action1:
const response1: Action1ResponseType[] = [
  {
    id: '456',
    name: 'helloworld',
    address: {
      id: '789'
      ...
    } 
  }
];

const response2: Action2ResponseType[] = [
  {
    id: '543',
    addressId: '789',
    addressValidation: {...}
  }
];

const response3: Action3ResponseType[] = [
  {
    id: '321',
    addressId: '789',
    addressHistory: {...}
  }
];
export const myEpic = (action$) => {
  return action$.pipe(
    ofType('myActionType'),
    switchMap((action) => {
      const x = ...; // Perform some initial work before API calls

      return forkJoin([
        action1(x),
        action2(x),
        action3(x),
      ]);
    }),
    // The following function is not correct.  Instead of receiving an array of responses, an array of request actions are passed.
    map(results => {
      const [response1, response2, response3] = results;
      const pageLoadData = ...; // Iterate the various address that are returned and attempt to merge data from response1, response2, and response2.

      return {
        type: 'PageLoaded',
        data: pageLoadData,
      };
    })
  );
};
1
Can you clarify what you mean by "wait for all of them to complete"? (i.e. after reducers are updated or their promises resolved) - kmui2
@stackoverflow-newbie, after the promises resolve. - Paul
Sorry, one more question, can you give an example of action1, action2, and action3? - kmui2
@stackoverflow-newbie, I added an example to the question. - Paul

1 Answers

0
votes
return forkJoin([
        action1(x),
        action2(x),
        action3(x),
      ]);

You have the right idea of returning the array of actions requests in the switchMap. If action1 and etc. do not need to be a Redux action, they may just return be a promise (like calling fetch) instead:

const action1 = (x) => fetch(url, 
    // ...
);

Then, map(results => { will contain the array of resolved responses from action1 and etc from switchArray.