NgRx 效果,ones 失败,不接受新动作
NgRx effect, ones failure occurs, does not accept new actions
@Injectable()
export class UserEffects {
constructor(
private store$: Store<fromRoot.State>,
private actions$: Actions,
private router: Router,
private chatService: ChatService,
private authService: AuthService,
private db: AngularFireAuth,
private http: HttpClient
) { }
@Effect()
login$: Observable<Action> = this.actions$.pipe(
ofType(UserActions.LOGIN),
switchMap((action: UserActions.LoginAction) =>
from(this.db.auth.signInWithEmailAndPassword(action.payload.email, action.payload.password)),
),
// switchMapTo(from(this.db.auth.currentUser.getIdToken())),
switchMapTo(from(this.db.authState.pipe(
take(1),
switchMap((user)=>{
if (user)
return from(user.getIdToken());
else
return of(null);
})
))),
switchMap(token => this.http.post(environment.apiUrl + '/api/login', { token: token })),
tap((response: any) => {
if (response.valid === 'true') {
localStorage.setItem('token', response.token);
this.router.navigate(['dash']);
}
}),
map(response => new UserActions.LoginSuccessAction({ response })),
catchError(error => {
return of({
type: UserActions.LOGIN_FAILURE,
payload: error
});
})
);
@Effect({ dispatch: false })
loginSuccess$: Observable<Action> = this.actions$.pipe(
ofType(UserActions.LOGIN_SUCCESS),
tap((action: UserActions.LoginSuccessAction) => {
console.log("LOGIN_SUCCESS");
console.log(action);
}));
@Effect({ dispatch: false })
loginFailure$: Observable<Action> = this.actions$.pipe(
ofType(UserActions.LOGIN_FAILURE),
tap((action: UserActions.LoginFailureAction)=>{
console.log("LOGIN_FAILURE");
console.log(action.payload.code);
}));
}
用例:
您位于登录页面。您输入用户名和密码以调用 LoginAction。如果一切顺利,应该调用 LoginSuccessAction。否则,应调用 LoginFailureAction。
除一种情况外一切正常:
LoginFailureAction 一旦被调用一次,LoginSuccessAction 和LoginFailureAction 都不会被再次调用。我不知道为什么会这样。我认为这可能与以下行有关:
catchError(error => {
return of({
type: UserActions.LOGIN_FAILURE,
payload: error
});
})
但是我在这里迷路了。我不是反应式编程方面的专家,但除了这种情况外,一切都按预期进行。有谁知道为什么会发生这种情况?
您必须在每个内部可观察对象上添加 catchError
,例如
switchMap(token => this.http.post(environment.apiUrl + '/api/login', { token: token }).pipe(catchError(...)),
有关详细信息,请参阅 NgRx 文档中的 handling errors 部分。
效果尊重成功完成和错误。如果出现错误,ngrx 将重新订阅,如果成功完成,则不会。
例如 catchError
可能会导致这种情况,因为它不监听其父流。如果您想在出现错误时启用流,您需要在 catchError
.
之后立即使用 repeat
运算符
catchError(error => {
return of({
type: UserActions.LOGIN_FAILURE,
payload: error
});
}),
repeat(), // <- now effect is stable.
@Injectable()
export class UserEffects {
constructor(
private store$: Store<fromRoot.State>,
private actions$: Actions,
private router: Router,
private chatService: ChatService,
private authService: AuthService,
private db: AngularFireAuth,
private http: HttpClient
) { }
@Effect()
login$: Observable<Action> = this.actions$.pipe(
ofType(UserActions.LOGIN),
switchMap((action: UserActions.LoginAction) =>
from(this.db.auth.signInWithEmailAndPassword(action.payload.email, action.payload.password)),
),
// switchMapTo(from(this.db.auth.currentUser.getIdToken())),
switchMapTo(from(this.db.authState.pipe(
take(1),
switchMap((user)=>{
if (user)
return from(user.getIdToken());
else
return of(null);
})
))),
switchMap(token => this.http.post(environment.apiUrl + '/api/login', { token: token })),
tap((response: any) => {
if (response.valid === 'true') {
localStorage.setItem('token', response.token);
this.router.navigate(['dash']);
}
}),
map(response => new UserActions.LoginSuccessAction({ response })),
catchError(error => {
return of({
type: UserActions.LOGIN_FAILURE,
payload: error
});
})
);
@Effect({ dispatch: false })
loginSuccess$: Observable<Action> = this.actions$.pipe(
ofType(UserActions.LOGIN_SUCCESS),
tap((action: UserActions.LoginSuccessAction) => {
console.log("LOGIN_SUCCESS");
console.log(action);
}));
@Effect({ dispatch: false })
loginFailure$: Observable<Action> = this.actions$.pipe(
ofType(UserActions.LOGIN_FAILURE),
tap((action: UserActions.LoginFailureAction)=>{
console.log("LOGIN_FAILURE");
console.log(action.payload.code);
}));
}
用例: 您位于登录页面。您输入用户名和密码以调用 LoginAction。如果一切顺利,应该调用 LoginSuccessAction。否则,应调用 LoginFailureAction。
除一种情况外一切正常:
LoginFailureAction 一旦被调用一次,LoginSuccessAction 和LoginFailureAction 都不会被再次调用。我不知道为什么会这样。我认为这可能与以下行有关:
catchError(error => { return of({ type: UserActions.LOGIN_FAILURE, payload: error }); })
但是我在这里迷路了。我不是反应式编程方面的专家,但除了这种情况外,一切都按预期进行。有谁知道为什么会发生这种情况?
您必须在每个内部可观察对象上添加 catchError
,例如
switchMap(token => this.http.post(environment.apiUrl + '/api/login', { token: token }).pipe(catchError(...)),
有关详细信息,请参阅 NgRx 文档中的 handling errors 部分。
效果尊重成功完成和错误。如果出现错误,ngrx 将重新订阅,如果成功完成,则不会。
例如 catchError
可能会导致这种情况,因为它不监听其父流。如果您想在出现错误时启用流,您需要在 catchError
.
repeat
运算符
catchError(error => {
return of({
type: UserActions.LOGIN_FAILURE,
payload: error
});
}),
repeat(), // <- now effect is stable.