Несколько действий в эффекте NGRX - PullRequest
0 голосов
/ 24 августа 2018

При изучении Angular и NGRX столкнулся с тем, что, как мне показалось, будет простым примером распространенной проблемы, но у него возникли проблемы с пониманием лучшего способа реализации логики управления с помощью шаблонов хранилища \ эффектов Redux.

Общий процесс:

Пользователь вводит информацию о кредитной карте, нажимает кнопку оплаты> Отправляет «GetTokenAction» из компонента> Отправляет Http-запрос к внешнему стороннему API для токенизации> Отправляет эту информацию в случае успеха в Payment API

Вот моя последняя попытка:

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

Вопрос / Соображения:

Является ли эффект подходящим местом для этого?Первая рабочая версия имела компонент, управляющий потоком и распределяющий несколько действий, также мог обрабатываться в службах, не зная, что является лучшей практикой.

Какой предпочтительный метод для уведомления об ошибках в шаблоне Effects?В Интернете и в примерах приложений есть много простых примеров, но у меня возникают проблемы с переводом этого в несколько более сложный пример (проверьте ответ, затем сгенерируйте ошибки и при необходимости остановите обработку).В настоящее время приложение делает что-то вроде этого:

    <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);

Может ли это быть проще?Должны ли ошибки быть объединены в один массив PayError?Есть ли ловушка на уровне компонента, если он подписан, или все это нужно обрабатывать на уровне эффектов?

1 Ответ

0 голосов
/ 28 августа 2018

Во-первых, не выполняйте функцию стрелок напрямую и вместо этого создавайте селекторы.

Во-вторых, выберите ViewModel (transactionInfo), который необходим для этого компонента с одним селектором вместо трех разных.Вы можете объединить несколько селекторов для достижения этой цели.Результат может быть увеличен в шаблоне с помощью *ngIf, например

<ng-container *ngIf="transactionInfo$ | async as transactionInfo">
  <span class="error" *ngFor="let error of tokenErrors">{{error.description}}</span>
    <span class="error" *ngFor="let error of transactionInfo.paymentErrors">{{error.description}}</span>
    <div class="success" *ngIf="transactionInfo.transactionStatus === 'approved'">Success</div>
</ng-container>
...