NgRx效果,发生失败,不接受新的动作

dev*_*am6 6 javascript rxjs ngrx ngrx-effects angular

@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);
      }));
}
Run Code Online (Sandbox Code Playgroud)

用例:您位于登录页面。您输入用户名和密码来调用 LoginAction。如果一切顺利,应该调用 LoginSuccessAction。否则,应调用 LoginFailureAction。

除了一种情况外,一切正常:
一旦 LoginFailureAction 被调用一次,LoginSuccessAction 和 LoginFailureAction 都不会被再次调用。我不知道为什么会发生这种情况。我认为这可能与该行有关:

catchError(error => {
  return of({
    type: UserActions.LOGIN_FAILURE,
    payload: error
  });
})
Run Code Online (Sandbox Code Playgroud)

但我在这里迷路了。我不是反应式编程方面的专家,但除了这一种情况之外,一切都按预期工作。有谁知道为什么会发生这种情况?

sat*_*ime 10

效果尊重成功完成和错误。如果出现错误,ngrx 将重新订阅,如果成功完成,则不会重新订阅。

例如,catchError可能会导致这种情况,因为它不监听其父流。如果您想在发生错误时启用流,您需要repeat在之后立即使用运算符catchError

    catchError(error => {
      return of({
        type: UserActions.LOGIN_FAILURE,
        payload: error
      });
    }),
    repeat(), // <- now effect is stable.
Run Code Online (Sandbox Code Playgroud)