【问题标题】:NgRx effect, ones failure occurs, does not accept new actionsNgRx 效果,出现失败,不接受新动作
【发布时间】:2020-05-27 03:19:13
【问题描述】:
@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
  });
})

但在这里我迷路了。我不是反应式编程方面的专家,但除了这种情况外,它都可以正常工作。有谁知道为什么会这样?

【问题讨论】:

    标签: javascript angular rxjs ngrx ngrx-effects


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      您必须在每个内部可观察对象上添加catchError,例如

      switchMap(token => this.http.post(environment.apiUrl + '/api/login', { token: token }).pipe(catchError(...)),
      

      有关详细信息,请参阅 NgRx 文档中的 handling errors 部分。

      【讨论】:

      • 天啊,NgRx 团队成员!谢谢你:)
      猜你喜欢
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-22
      • 2019-01-31
      • 1970-01-01
      • 2018-01-11
      • 1970-01-01
      相关资源
      最近更新 更多