RxJs and redux-observable. Append value when ajax succeed or failed

I have the following epic:

export const changeTeamSubscriptionPlan = (braintreePlanId: string) => ({
  type: CHANGE_TEAM_SUBSCRIPTION_PLAN,
  braintreePlanId,
});

export const changeTeamSubscriptionPlanEpic = (action$: any, store: Store<ReduxState, *>) =>
  action$.ofType(CHANGE_TEAM_SUBSCRIPTION_PLAN)
    .mergeMap(({ braintreePlanId }) => {
      const state = store.getState();
      const { subscription_id } = state.payment.subscription;
      let request;
      if (subscription_id) {
        request = ajax(api.changeTeamSubscriptionPlan(subscription_id, braintreePlanId));
      } else {
        const [method] = state.payment.paymentMethods;
        request = ajax(api.createSubscription(braintreePlanId, method.token));
      }

      // I would like to emit another value ({ type: FETCH_TEAM }) no matter what happens 
      //(basically I try to invalidate the team data even if the request fails)
      return request
        .map(response => ({
          type: CHANGE_TEAM_SUBSCRIPTION_PLAN + SUCCESS,
          payload: {
            data: response.response,
            status: response.status,
          },
        }))
        .catch(error => Observable.of({
          type: CHANGE_TEAM_SUBSCRIPTION_PLAN + FAILURE,
          response: {
            data: error.xhr.response,
            status: error.xhr.status,
          },
        }));
    });

What I want to do is no matter if ajax call ends with catch or calls map I want to append another value.

I run out of ideas, so I'm hoping for help.

1 answer

  • answered 2018-01-12 09:47 Tomasz

    After switching to original operators it turned out that I can do this:

      return request
        .map(response => ({
          type: CHANGE_TEAM_SUBSCRIPTION_PLAN + SUCCESS,
          payload: {
            data: response.response,
            status: response.status,
          },
        }))
        .catch(error => Observable.of({
          type: CHANGE_TEAM_SUBSCRIPTION_PLAN + FAILURE,
          error: mapToError(error),
        }))
        .concat(Observable.of({ type: 'CHUJ_TYPE' }));
    

    and concat will append value even when the catch block fires.

    I was originally using custom operator which I though will work just like catch does but will reduce boilerplate in my app:

    Observable.prototype.mapFailure = function catchAndMapError(ACTION_TYPE, optionalPayload = {}) {
      return Observable.create(subscriber =>
        this.subscribe(
          value => subscriber.next(value),
          (error) => {
            try {
              const action = {
                type: ACTION_TYPE + FAILURE,
                error: {
                  ...mapToError(error),
                  ...optionalPayload,
                },
              };
              subscriber.next(action);
            } catch (e) { // catch mappings error
              subscriber.error(e);
            }
          },
          () => subscriber.complete(),
        ),
      );
    };
    

    It seems like it doesn't work the same as catch.....