6

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

下面的代码;

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);
      // });
  }
}
4

2 回答 2

10

当捕获到错误时,返回的 observablecatch用于继续链。并且返回的 observable 完成,它完成了效果并看到ngrx取消订阅效果。

mapandcatch移入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不会完成效果。

于 2017-08-05T15:50:30.993 回答
1

快乐之路场景快乐的路径流 ngrx 效果

错误场景:需要 reducer 来处理错误情况并在需要时向用户显示一些消息。 错误场景ngrx-effects

通过使用pipecatchErrorfrom,rxjs/operators我们可以将两个(或所有)错误案例重新映射到单个 ErrorAction 中,然后我们可以直接在 ui 中进行处理effects并进行副作用 ui 更改。

@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)))
);
于 2019-06-11T18:58:58.053 回答