我需要我的代码的帮助。我是新手,我对ngrx的效果有疑问。因此,在我的身份验证服务中,我声明了登录失败,该登录类型是可观察的,我希望当身份验证失败登录时,微调框停止旋转并再次输入数据。我应该在ngrx / effect中添加什么部分?
SERVICE COMPONENT
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>
嗯,有很多方法。我会说以下。这里有2个州。一种是authentication状态,一种是loading状态。
您应该有2个减速器,其中一个处理loading状态,另一个处理authentication部分。
通常取决于UX设计,您希望微调器在每次请求完成时都显示为叠加,而与您所在的页面/组件无关。
实现此目的的一种方法是,通过创建一个用于创建此叠加层的LoadingService,与该loadState一起使用的loadingService(该示例使用来自Angular Material的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())));
}
}
每次完成请求时,加载状态都会增加,而当请求完成(失败或失败)时,状态会减少。正在加载服务会订阅此状态,并通过显示/隐藏/保留叠加层来对更改做出反应。
一旦完成,每次完成请求(包括身份验证)时,就会出现加载。
对于您的示例,应该在效果内分派一个在执行请求时显示加载的动作,并分派一个在成功和错误情况(catchError()= > {...})。您可以从一个效果返回多个动作
return [{
type: AuthActionTypes.LoginSuccessAction,
payload: user
}, {
type: LoginActionTypes.DecrementLoading,
}]
并且您还应该在执行auth请求之前分派增加负载的操作。
this.store.dispatch(new LoadingIncrementAction())
this.authService.login(action.payload).