angular - 角度:身份验证失败时如何阻止微调器加载?
问题描述
我的代码需要帮助。我是角度方面的新手,我对ngrx的效果有疑问。因此,在我的身份验证服务中,我声明了一个可观察类型的登录失败,我希望当我的身份验证登录失败时,微调器停止旋转并再次输入数据。我应该在 ngrx/effect 中添加什么部分?
服务组件
public loginFailed: Observable<boolean>;
NGRX/效果
@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个州。一种是认证状态,一种是加载状态。
您应该有 2 个减速器,一个处理加载状态,一个处理身份验证部分。
根据 UX 设计,您通常希望每次完成请求时微调器都显示为覆盖,与您所在的页面/组件无关。
实现此目的的一种方法是使用 LoadingService 创建此叠加层,loadingService 与 loadingState 一起使用(该示例使用来自 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,
}]
并且您还应该在执行身份验证请求之前调度增加加载的操作。
this.store.dispatch(new LoadingIncrementAction())
this.authService.login(action.payload).
推荐阅读
- ajax - Express.js and axios route timeout
- java - onClickListner in RecyclerViewer
- fortran - The accuracy of fortran double precision
- drop-down-menu - Materialise 的下拉菜单不起作用
- bash - 如何确定 bash 中是否安装了 npm 模块
- python - 将带有字符串的嵌套列表转换为 Pandas Dataframe
- node.js - Node.JS 字符串只匹配第一个字符
- validation - 表单数据验证
- c# - MVC Core 存储库查询选择所有列
- r - 如何找出新的 NaN 来自哪里 - R