Reputation: 3707
I'm learning Angular2, coming from years of development in Angular 1.x. I've run into some issues with RxJS, and particularly how to catch and handle errors. In my example I'm trying to authenticate a user, by passing a Facebook access token to our own API. This works great when it works, but I can't seem to get the error handling to work the way I expect it to.
The method call hierarchy is as follows
SignInComponent.facebookLoginResponse
=> AuthService.facebookLogin
=> APIService.Post
When the server returns an error (status code 4xx), I expect the client to map the error and catch it in my SignInComponent error handling block. Instead the console shows me the following errors (the ErrorHandler.handle
is never called):
-> EXCEPTION: [object Object] core.umd.js:3488
-> Uncaught > Object {errors: Array[1]} Subscribe.ts:241
Below are the relevant snippets of code
export class SignInComponent{
...
public facebookLoginResponse(response : FB.LoginStatusResponse){
if (response.status == "connected"){
let observable = this.auth.facebookLogin(response.authResponse.accessToken);
observable.subscribe(() => {
this.router.navigate(['influencer']);
}, (error : ErrorResponse) => {
ErrorHandler.handle(error, "Couldn't log in due to the following reasons:");
});
}
}
...
}
export class Auth{
...
facebookLogin(accessToken : String) : Observable<AuthResponse>{
let observable = this.api.Post<AuthResponse>("influencer/auth/facebook", {
token: accessToken
});
observable.subscribe((response : AuthResponse) => {
Auth.handleAuthSuccess(response, SessionType.Influencer);
});
return observable;
}
...
}
export class API{
...
public Post<T>(path : String, postData) : Observable<T>{
return this.http.post(this.basePath + path, postData)
.map((response : Response) => {
return API.extractData<T>(response);
})
.catch(API.handleError)
.share();
}
private static extractData<T>(response : Response) : T{
return <T>response.json();
}
private static handleError (error: Response) {
let errorResponse : ErrorResponse;
...
return Observable.throw(errorResponse);
}
...
}
It seems like the share
call in API.Post
breaks the error handling. However without it, the request is sent as many times as we have subscribed to the observable (in this case, two times). How should I do this correctly?
Upvotes: 0
Views: 274
Reputation: 16892
Not sure if the following applies to your case, but in most cases "splitting up" a stream into multiple subscriptions is not necessary when writing processes sequential(which should be no problem in most cases, since there is onyl 1 thread anyways), in your case try to remove the share()
and use the following:
export class Auth {
...
facebookLogin(accessToken : String) : Observable<AuthResponse>{
return this.api.Post<AuthResponse>("influencer/auth/facebook", {
token: accessToken
})
.do((response : AuthResponse) => Auth.handleAuthSuccess(response, SessionType.Influencer));
}
...
}
Upvotes: 0