【问题标题】:Angular2 + ngrx/store for handling failure HTTP requestsAngular2 + ngrx/store 用于处理失败的 HTTP 请求
【发布时间】:2016-05-24 20:54:01
【问题描述】:

我想要一个用于创建和调度 HTTP 操作的简单代码路径。我想做的是:

this.http.request(...)
  .map((res: Response) => res.json())
  .catch((err: any) => err.json())
  .map((payload: any) => { type: 'SUCCESS', payload })
  .catch((payload: any) => { type: 'FAILURE', payload})
  .subscribe((action: Action) => this.store.dispatch(action));

这样,成功和失败响应都将转换为 JSON,然后根据成功/失败标准分配正确的缩减类型,以便可以正确操作存储。 (想想用户登录成功和失败返回 200 或 401)。

有没有更清洁或更好的方法来处理这个问题?当前第二个.catch 表现不佳,因为它没有返回可观察对象。

欢迎提出建议或其他解决方案?

【问题讨论】:

    标签: angular redux rxjs ngrx


    【解决方案1】:

    from example-app from ngrx,对于这种情况推荐使用@Effects(查看docs文件夹),而IMO,是更清晰的方式,查看服务:

    @Injectable()
    export class AuthService {
        private headers: Headers;
        private API_ENDPOINT: string = "/api/user/";
    
        public constructor(
            private http: Http,
            private localStorageService: LocalStorageService
            ) {
            this.headers = new Headers({ 'Accept': 'application/json' });
        }
    
        public login(email: string, password: string): Observable<AuthUser> {
            return this.http
            .post(this.API_ENDPOINT + 'login', { 'email': email, 'password': password }, this.headers)
            .map(res => res.json().data as AuthUser)
            .catch(this.handleError);
        }
    
        private handleError(error: Response | any) {
            let body = error.json();
            // .. may be other body transformations here
            console.error(body);
            return Observable.throw(body);
        }
    }
    

    并检查效果:

    @Injectable()
    export class AuthEffects {
    
        constructor(
            private actions$: Actions,
            private authService: AuthService,
            private localStorageService: LocalStorageService
        ) { }
    
        @Effect() logIn$: Observable<Action> = this.actions$
            .ofType(auth.ActionTypes.LOGIN)
            .map((action: Action) => action.payload as LoginCredentials)
            .switchMap((credentials: LoginCredentials) => this.authService.login(credentials.email, credentials.password))
            .do((user: AuthUser) => this.localStorageService.setUser(user))
            .map((user: AuthUser) => new auth.LoginSuccessAction(user))
            .catch((error) => of(new auth.FlashErrors(error)));
    
    }
    

    当然,你需要在 appModule 上设置 Effects:

    @NgModule({
    imports: [
        StoreModule.provideStore(reducer),
        EffectsModule.run(AuthEffects),
        RouterStoreModule.connectRouter(), // optional but recommended :D
    ],
    declarations: [...],
    providers: [AuthService, LocalStorageService, ...]
    })
    export class AuthModule {}
    

    从 repo 中的 docs 文件夹中阅读有关 ngrx/effects 的更多信息。

    【讨论】:

    • 不会在连接错误时调用new auth.LoginSuccessAction(user) 吗?
    【解决方案2】:

    在我的一项服务中,我这样做:

    get(url, actionType) {
      this._http.get(BASE_URL + url)
        .map(response => response.json())
        .map(payload => ({ type: actionType, payload }))
        .subscribe(action => this.store.dispatch(action), error => this._apiErrorHandler(error));
    }
    
    private _apiErrorHandler(response) {
      let payload = response.json().error;
      this.store.dispatch({ type: 'API_ERROR', payload });
    }
    

    【讨论】:

      猜你喜欢
      • 2016-09-07
      • 1970-01-01
      • 1970-01-01
      • 2022-12-16
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      • 2020-06-10
      相关资源
      最近更新 更多