错误后 rx 损坏时可观察到 [英] Observable with rx broken after error

查看:22
本文介绍了错误后 rx 损坏时可观察到的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 ngrx store + ng 效果为我的应用编写登录流程.我设法编写了它并且它在快乐的场景中工作,但是当用户向表单输入错误的值时,服务器以 401 响应,下一次登录尝试无效.我已经读到,在使用 observable 时必须捕获异常,以免破坏"流,但据我所知,我捕获了异常并且现在仍在工作.

Im trying to write login flow for my app using ngrx store + ng effects. I have managed to write it and it works in happy scenerio, but when user inputs wrong values to the form, so that server responds with 401, the next login attempt has no effects. I have read that the exception must be catch when working with observables in order not to 'break' the stream, but as far i know I'm catch the exception and still its now working.

在代码下方;

export class LoginComponent {

  logged = new Observable<any>();

  constructor(private store: Store<AppStore>) {
   this.logged = store.select('login');
  }

  login(username: string, password: string){
    let body = JSON.stringify({username, password});
    this.store.dispatch({type: LoginActions.ATTEMPT_LOGIN, payload: body});
  }

}

@Injectable()
export class LoginEffects {

  constructor(
    private actions: Actions,
    private loginService: LoginService
  ) { }

  @Effect() login = this.actions
    .ofType(LoginActions.ATTEMPT_LOGIN)
    .map(toPayload)
    .switchMap(payload => this.loginService.attemptLogin(payload))
    .map(response => new LoginActions.LoginSuccess(response))
    .catch(error => of(new LoginActions.LoginFailed(error)));

  @Effect() success = this.actions
    .ofType(LoginActions.LOGIN_SUCCESS)
    .map(toPayload)
    .map(payload => localStorage.setItem(Global.TOKEN, payload))
    .map(() => go(['/menu']));

  @Effect() error = this.actions
    .ofType(LoginActions.LOGIN_FAILED)
    .map(toPayload)
    .map(payload => console.log(payload))
    .ignoreElements();
}

export const login = (state: any = null, action: Actions) => {
  switch (action.type) {
    case LoginActions.ATTEMPT_LOGIN:
      console.log('hello from reducer attempt login');
      return action.payload;
    case LoginActions.LOGIN_SUCCESS:
      console.log('hello from reducer success login');
      return action.payload;
    case LoginActions.LOGIN_FAILED:
      console.log('hello from reducer failed login');
      return action.payload;
    default:
      return state;
  }
};

@Injectable()
export class LoginService {

  auth = new Observable<any>();
  constructor(private store: Store<AppStore>, private http: Http) {
    this.auth = store.select('auth');
  }

  attemptLogin(payload): Observable<any> {
    // let body = JSON.stringify({username, password});
    return this.http.post(Global.API_URL + '/login', payload)
      .map(response => response.headers.get('Authorization'));
      // .map(action => (
      //   { type: LoginActions.ATTEMPT_LOGIN, payload: action}))
      // .subscribe(action => {this.store.dispatch(action);
      // });
  }
}

推荐答案

当一个错误被捕获时,catch 返回的 observable 被用来继续这个链.并且返回的 observable 完成,即完成效果,看到 ngrx 取消订阅效果.

When an error is caught, the observable returned by catch is used to continue the chain. And the returned observable completes, which completes the effect and sees ngrx unsubscribe from the effect.

mapcatch移动到switchMap中:

@Effect() login = this.actions
.ofType(LoginActions.ATTEMPT_LOGIN)
.map(toPayload)
.switchMap(payload => this.loginService.attemptLogin(payload)
  .map(response => new LoginActions.LoginSuccess(response))
  .catch(error => of(new LoginActions.LoginFailed(error)))
);

switchMap 内部捕获不会完成效果.

Catching inside the switchMap won't complete the effect.

这篇关于错误后 rx 损坏时可观察到的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆