Angular2 + ngrx/store 用于处理失败的 HTTP 请求
Angular2 + ngrx/store for handling failure HTTP requests
我想要一个简单的代码路径来创建和调度 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,然后根据 success/fail 标准分配正确的缩减类型,以便可以正确操作商店。 (想想用户登录成功和失败哪个returns一个200或者401)。
是否有更清洁或更好的处理方法?当前第二个 .catch
表现不佳,因为它没有返回可观察值。
欢迎提出建议或其他解决方案?
在我的一项服务中,我是这样做的:
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 });
}
来自example-app from ngrx
, for this case is recommended to use @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 {}
在存储库的文档文件夹中阅读有关 ngrx/effects 的更多信息。
我想要一个简单的代码路径来创建和调度 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,然后根据 success/fail 标准分配正确的缩减类型,以便可以正确操作商店。 (想想用户登录成功和失败哪个returns一个200或者401)。
是否有更清洁或更好的处理方法?当前第二个 .catch
表现不佳,因为它没有返回可观察值。
欢迎提出建议或其他解决方案?
在我的一项服务中,我是这样做的:
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 });
}
来自example-app from ngrx
, for this case is recommended to use @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 {}
在存储库的文档文件夹中阅读有关 ngrx/effects 的更多信息。