While learning Angular and NGRX, ran into what I thought would be simple example of common problem but having trouble understanding best way to accomplish the control logic with in the Redux store\effects patterns.

General Process:

User types in credit card info, hit pay button > Dispatch a "GetTokenAction" from component > Make an Http request to external 3rd party API to tokenize > Submit that information if successful to Payment API

Here is my latest attempt:

    @Effect() getToken$ = this.actions$
    .ofType(TokenizerActions.GET_TOKEN)
    .pipe(switchMap((action: TokenizerActions.GetTokenAction) => {
        return this.TokenizerApiService.getToken(action.payload)
            .pipe(
                map(tokenResponse => {
                        console.log(tokenResponse);
                        // service will return 200 with "declined" status. In this case I want to treat it like an Error.
                        if (tokenResponse.results.Error != null) {
                            return new TokenizerActions.GetTokenFailedAction(tokenResponse.results.Error.messages);
                        }
                        // What is best practice here?  Call Payment Service? Dispatch Actions? Where should this mapping logic live?
                        const paymentRequest: PaymentRequest = new PaymentRequest();
                        paymentRequest.token = tokenResponse.results.token;
                        paymentRequest.amount = action.payload.amount;
                        paymentRequest.customerNumber = action.payload.customerNumber;
                        paymentRequest.correlationId = tokenResponse.results.correlation_id;
                        // this does not work, "dispatched an invalid action: undefined" error.
                        mergeMap((payReq: PaymentRequest) => [new paymentActions.MakePaymentAction(paymentRequest),
                        new TokenizerActions.GetTokenSuccessAction(tokenResponse.results.token)]);
                    }),
                catchError(error => of(new TokenizerActions.GetTokenFailedAction(error)))
            );
    }));

constructor(
    private actions$: Actions,
    private TokenizerApiService: TokenizerApiService,
    private paymentApiService: PaymentApiService
) { }

Question/Considerations:

Is the effect the appropriate place to handle this? The first working version had the component controlling the flow and dispatching multiple actions, could also be handled within the services, not sure which is best practice.

What is the preferred method for error notification within the Effects pattern? Online and in sample application there are a lot of simple examples, but I am having trouble translating that to a slightly more complex example (inspect response and then throw errors and stop processing as needed). Currently the application is doing something like this:

    <span class="error" *ngFor="let error of tokenErrors$ | async">{{error.description}}</span>
    <span class="error" *ngFor="let error of paymentErrors$ | async">{{error.description}}</span>
    <div class="success" *ngIf="(payment$ | async)?.transactionStatus === 'approved'">Success</div>

this.paymentErrors$ = this.store.select(state => state.payment.paymentErrorMessages);
this.tokenErrors$ = this.store.select(state => state.token.tokenErrorMessages);
this.payment$ = this.store.select(state => state.payment.paymentStatus);

Can it be simpler? Should errors be combined into one PayError array? Is there a catch in the component level if subscribed or is it all to be handled in the effects level?

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.