2016-01-28 30 views
24

Sto lavorando a un'app Angular 2 e ho bisogno di alcune indicazioni su come gestire gli errori di autenticazione in modo pulito.Angular 2 - Gestione di più abbonamenti su un singolo osservabile

Il mio obiettivo finale è essere in grado di gestire centralmente gli errori di autenticazione (in particolare 401 e 403) per ogni richiesta Http.

Ho trovato la domanda this super utile per iniziare, tuttavia sono bloccato sul modo corretto di registrare il mio gestore di errori per ogni osservabile restituito dall'implementazione personalizzata Http.

Ecco un esempio di quello che sto attualmente lavorando con:

import {Injectable} from 'angular2/core'; 
    import {Http, ConnectionBackend, Request, RequestOptions, RequestOptionsArgs, Response} from 'angular2/http'; 

    import {Observable} from 'rxjs/Observable'; 


    @Injectable() 
    export class ClauthHttp extends Http { 

    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) { 
     super(backend, defaultOptions); 
    } 

    get(url: string, options?: RequestOptionsArgs): Observable<Response> { 
     var response = super.get(url, options); 

     return this._handleSecurityResponse(response); 
    } 

    /* 
    Other overrides omitted for brevity... 
    */ 

    private _handleSecurityResponse(response: Observable<Response>):  Observable<Response> { 
     response.subscribe(null, (error: Response) => { 
      // Do some nifty error handling here. 
     }); 

     return response; 
    } 
} 

La soluzione di cui sopra "lavora" con un intoppo ... Ogni richiesta HTTP è fatto due volte. Non va bene.

Qualche consiglio su come farlo correttamente?

(Update) Codice di lavoro

Sulla base delle informazioni in risposta accettata qui è ciò che la classe assomiglia nella sua forma correttamente funzionante.

import {Injectable} from 'angular2/core'; 
    import {Http, ConnectionBackend, Request, RequestOptions, RequestOptionsArgs, Response} from 'angular2/http'; 

    import {Observable} from 'rxjs/Observable'; 
    import 'rxjs/add/operator/share'; 


    @Injectable() 
    export class ClauthHttp extends Http { 

    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) { 
     super(backend, defaultOptions); 
    } 

    get(url: string, options?: RequestOptionsArgs): Observable<Response> { 
     var response = super.get(url, options); 

     return this._handleSecurityResponse(response); 
    } 

    /* 
    Other overrides omitted for brevity... 
    */ 

    private _handleSecurityResponse(response: Observable<Response>):  Observable<Response> { 
     var sharable = response.share(); 

     sharable.subscribe(null, (error: Response) => { 
      // Do some nifty error handling here. 
     }); 

     return sharable; 
    } 
} 

risposta

29

Ciò è probabilmente dovuto al fatto che il vostro è un Observable<Response> osservabile freddo, vale a dire che è 'riavviato' per ogni nuovo abbonato. Per una spiegazione degli osservabili caldi e freddi, dai un'occhiata a Hot and Cold observables : are there 'hot' and 'cold' operators?. Quindi qui probabilmente sottoscrivi una volta il gestore dei risultati, e un'altra volta il gestore degli errori.

Si dovrebbe essere in grado di aggirare l'effetto abbonamenti fianco a 'condividere' il tuo osservabile,

cioè sostituire

var response = super.get(url, options); 

Con

var response = super.get(url, options).share();` 
+0

Thanks..this è esattamente quello che stavo cercando – prash