ANGULAR: Как остановить загрузку счетчика при сбое аутентификации? - PullRequest
0 голосов
/ 25 октября 2019

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

СЕРВИСНЫЙ КОМПОНЕНТ

 public loginFailed: Observable<boolean>;

NGRX / EFFECTS

 @Effect()
 public login$: Observable<any> = 
  this.actions$.pipe(
  ofType(AuthActionTypes.LoginAction),
  mergeMap((action: Login) => 
  this.authService.login(action.payload).
  pipe(
  map((user: User) => {

    if(user.username != null && user.password != null) {
      this.authService.loginFailed
    }

    return {
      type: AuthActionTypes.LoginSuccessAction,
      payload: user
    }
  }),
  catchError(() => {
    return of({

    });
  })
))

HTML

 <div fxLayoutAlign="center center" class="button">
    <button class="btn-login" type="button" color="primary" [disabled]="isLoginBtnDisabled" (click)="onSubmit()"
        mat-button>
   <mat-icon *ngIf="isLoginBtnDisabled; else loginText">
    <mat-spinner diameter="20"></mat-spinner>
  </mat-icon>
  <ng-template #loginText>Login</ng-template>
</button>

1 Ответ

0 голосов
/ 25 октября 2019

Ну, есть много подходов. Я бы сказал следующее. Здесь 2 состояния. Одним из них является состояние аутентификация , а другим - состояние загрузка .

У вас должно быть 2 редуктора, один из которых обрабатывает состояние загрузка , а другой аутентификация часть.

В зависимости от дизайна UX обычно вы хотите, чтобы спиннер отображался как оверлей каждый раз, когда выполняется запрос, независимо от того, на какой странице / компоненте вы находитесь.

Один из способов достижения этого - наличие службы загрузки, которая создает это наложение, загрузки службы, которая работает с loadingState (пример выполняется с использованием наложения CDK из углового материала).

@Injectable()
export class LoadingService {

  private overlayRef: OverlayRef;
  private currentCount = 0;

  constructor(private overlay: Overlay, private store: Store<ApplicationState>) {
    this.store.pipe(
      select(fromLoading.loadingState)
    ).subscribe(loadingState => {
        if (loadingState.count > this.currentCount) {
          if (this.currentCount === 0) {
            this.overlayRef = this.cdkOverlayCreate();
            this.overlayRef.attach(new ComponentPortal(MatSpinner));
          }
        } else if (loadingState.count === 0 && this.currentCount !== 0) {
          this.overlayRef.dispose();
        }
        this.currentCount = loadingState.count;
      }
    );
  }

  cdkOverlayCreate(): OverlayRef {
    return this.overlay.create(
      {
        hasBackdrop: true,
        backdropClass: 'dark-backdrop',
        positionStrategy: this.overlay.position()
          .global()
          .centerHorizontally()
          .centerVertically()
      }
    );
  }
}

Как я уже говорил, вы хотите, чтобы загрузка отображалась независимо от того, какой компонент вы на ней используете. Это подразумевает, что манипулирование состоянием должно выполняться с HTTP-перехватчика. Это может выглядеть так

@Injectable()
export class LoadingInterceptor implements HttpInterceptor {
  constructor(private store: Store<ApplicationState>) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.store.dispatch(new fromLoading.IncrementLoadingAction());
    return next.handle(req).pipe(
      finalize(() => this.store.dispatch(new fromLoading.DecrementLoadingAction())));
  }
}

Каждый раз, когда выполняется запрос, состояние загрузки увеличивается, а когда запрос завершается (сбой или нет), состояние уменьшается. Служба загрузки подписывается на это состояние и реагирует на изменения, показывая / скрывая / сохраняя оверлей.

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

Для вашего примера вы должны отправить действие показа загруженного при выполнении запроса, внутри эффекта, и отправить действие скрытия загрузчика как на success , так и ошибка (catchError () => {...}) . Вы можете вернуть несколько действий из эффекта

return [{
      type: AuthActionTypes.LoginSuccessAction,
      payload: user
    }, {
      type: LoginActionTypes.DecrementLoading,
    }]

, и вам также следует отправить действие увеличения загрузки перед выполнением запроса авторизации.

this.store.dispatch(new LoadingIncrementAction())
this.authService.login(action.payload).
...