8

我想要一个简单的代码路径来创建和调度 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)。

有没有更清洁或更好的方法来处理这个问题?当前的 2nd.catch表现不佳,因为它没有返回 observable。

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

4

2 回答 2

12

示例应用程序ngrx,对于这种情况,建议使用@Effects(检查文档文件夹),而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 上设置效果:

@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 的信息。

于 2017-01-24T05:30:24.660 回答
8

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

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-02-13T20:02:09.417 回答