问题描述
我注意到我正在建立的登录屏幕中有一个奇怪的行为。我想以特定方式处理GetUserFailures,因此我订阅了ScannedActionsSubject
并按操作类型进行过滤。
export class LoginComponent implements OnInit {
constructor(
private userService: UserService,private store: Store<AppState>,private actions$: ScannedActionsSubject,) {
...
}
ngOnInit() {
this.actions$
.pipe(filter((action: any) => action.type === '[User] Get User Failure'))
.subscribe((action: any) => {
const error = action.payload.error.response;
this.handleError(error);
if (error && error.includes('not found')) {
this.snackBar.open('Sorry,we have no record of that email address.','OK');
} else if (error && error.includes('Invalid credentials')) {
this.snackBar.open('The password you entered is incorrect.','OK');
}
if (this.loading) this.loading = false;
});
}
async login(event: any) {
if (event) event.preventDefault();
// if the user is logging in for the first time,show update password form
if (this.validateForm(this.loginForm)) {
this.loading = true;
const email = this.loginForm.controls.email.value;
email && this.store.dispatch(new GetUserByEmail(email));
this.store.select(selectUserByEmail)
.pipe(filter(result => result.user !== (null || undefined)))
.subscribe(
async (result) => {
this.user = result.user;
if (this.user && this.user.status === 'Pending') {
const email = this.loginForm.controls.email.value;
const password = this.loginForm.controls.password.value;
email && password && this.userService.validatePasswordHash(email,password).subscribe(
(result) => {
if (result) {
this.loading = false;
this.loginStepper.selectedindex = 2;
this.hidePassword = true;
}
},(error) => {
this.handleError(error);
if (error.error && error.error.response.includes('Invalid credentials')) {
this.snackBar.open('The password you entered is incorrect.','OK');
this.loading = false;
return;
}
},);
} else if (this.user && this.user.status === 'Active') {
localStorage.setItem('USER_AUTHD','true');
await this.router.navigateByUrl('/home');
this.snackBar.open(`Welcome back,${this.user.recipientFullName.split(' ')[0]}!`,'OK',{ duration: 4000 });
} else {
console.log('neither active nor pending!',this.user);
}
this.loading = false;
return;
},(error) => {
console.log('Error getting user by email',error);
return;
},() => { // complete
if (this.loading) this.loading = false;
},);
}
}
当发生错误时,错误会得到正确处理,但是当我尝试再次启动登录过程时,store.select
段会无限期挂起,并且我似乎无法找出原因。就可读性而言,它绝对不是最好的实现,但是我为工作功能提供了所有这些。
重申一下,在第一次登录尝试失败后,每次在登录流“挂起”之后,特别是this.store.select(selectUserByEmail)
内挂起之后,每次尝试登录,但是要跟踪挂起的原因很困难,因为我只能看到作为对GetUserByEmail的网络请求,该请求有效。
我希望能够“重新加载”系统以进行更多登录尝试。
GetUserByEmail效果:
@Injectable()
export class UserEffects {
@Effect()
getUserByEmail$: Observable<any> = this.actions$.pipe(
ofType<GetUserByEmail>(UserActionsEnum.GetUserByEmail),switchMap((action) => this.userService.getUserByEmail(action.payload)),map((response) => new GetUserSuccess(response)),catchError((error) => of(new GetUserFailure(error))),);
}
减速器:
case UserActionsEnum.GetUserByEmail:
return {
...state,user: action.payload?.data,loading: false,};
解决方法
最初的问题是由于错误,这种影响将被取消。因此,您可以做的是将catchError
的{{1}}的内部可观察区域移动:
switchMap