2016-02-13 26 views
8

Desidero avere un percorso di codice semplice per la creazione e l'invio di azioni HTTP. Quello che vorrei fare è qualcosa di simile:Angular2 + ngrx/store per problemi di gestione richieste 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)); 

In questo modo entrambe le risposte di successo e fallimento sono convertiti in JSON e poi basano sul successo/fail criteri assegnano il tipo di riduzione corretta in modo che il negozio può essere azionata su correttamente. (pensa al login utente riuscito e al fallimento che restituisce un 200 o un 401).

Esiste un modo più pulito o migliore per gestirlo? L'attuale 2 .catch non funziona bene poiché non restituisce un osservabile.

Suggerimenti o altre soluzioni sono benvenute?

risposta

7

In uno dei miei servizi lo faccio in questo modo:

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 }); 
} 
11

Dal example-app da ngrx, per si raccomanda questo caso di utilizzare @Effects (controllare la cartella Documenti), e IMO, è una più chiara modo, controllare il servizio:

@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); 
    } 
} 

E controllare l'effetto:

@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))); 

} 

Fuori rotta, è necessario impostare gli effetti sulla appModule:

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

Leggi di più riguardo NGRX/effetti sulla cartella docs dalla repo.

+0

Non si chiama 'new auth.LoginSuccessAction (utente)' su errore di connessione? – maurycy