Vojtech
Vojtech

Reputation: 2603

How to handle HTTP errors in API service and return response through Observable only in case of success?

In my Angular2 app I have an api.service with method sendRequest that should do following:

  1. Sends request to the server
  2. Returns promise to the caller (I want callers to get success responses only)
  3. If error occured handle the error localy (navigate user to login or show a popup)

I implemented it using Promise:

sendRequest(method: string, url: string, data: any) : Promise<any> {
    return this.http.request(method, url, {
        body: data,
        headers: {
            'Accept': 'application/json, text/plain, */*',
            'Authorization': 'bearer ' + token,
            'Content-Type': 'application/json;charset=UTF-8'
        }
    }).toPromise().catch((res) => this.handleError(res));
}

handleError(response: any) {
    if (response.status === 401 || response.status === 403) {
        this.tokenService.deleteToken();
        this.router.navigate(['login']);
    }
    // Show popup etc.
    ...
}

I'd like to replace promise by observable:

sendRequest(method: string, url: string, data: any) : Observable<any> {...}

Please advise how to do that. Thank you.

EDIT 1: I found examples that handled response and then passed some result to the observer. That's not what I need. If error occurs the observer shouldn't be notified at all. Observers should be notified only if a successful response arrived. If error occurs it should be processed inside api.service only.

Upvotes: 0

Views: 1992

Answers (3)

mittal bhatt
mittal bhatt

Reputation: 1009

sendRequest(method: string, url: string, data: any) : Observable<any> {
    return this.http.request(method, url, {
        body: data,
        headers: {
            'Accept': 'application/json, text/plain, */*',
            'Authorization': 'bearer ' + token,
            'Content-Type': 'application/json;charset=UTF-8'
        }
    }).map((response: Response) => <any>response.json()).catch(this.handleError);
}

handleError(response: any) {
    if (response.status === 401 || response.status === 403) {
        this.tokenService.deleteToken();
        this.router.navigate(['login']);
    }
    // Show popup etc.
    ...
}

//get response like below
  this.yoursevice.sendRequest(resdata)
        .subscribe((resdata) => {}, 
(error) => {
            this.statusMessage =
                'Problem with the service. Please try again after sometime';
            console.error(error);
        }););

Upvotes: 0

Atul
Atul

Reputation: 541

please see below -

sendRequest(method: string, url: string, data: any) : Observable<any>{
    return this.http.request(method, url, {
        body: data,
        headers: {
            'Accept': 'application/json, text/plain, */*',
            'Authorization': 'bearer ' + token,
            'Content-Type': 'application/json;charset=UTF-8'
        }
    }).map( ( res ) => {
      return res || {};
    } )
    .catch( this.handleError );
}



handleError(response: any) {
    if (response.status === 401 || response.status === 403) {
        this.tokenService.deleteToken();
        this.router.navigate(['login']);
    }
    // Show popup etc.
    ...
}

Upvotes: 1

bugs
bugs

Reputation: 15323

http.request returns an Observable by default, but you are converting it to a Promise with .toPromise()

Simply change the signature of the function to return Observable<any> and remove the part where you convert the Observable to a Promise (.toPromise().catch((res) => this.handleError(res))).

You'll also need to change the way you listen to the response (you'll most likely have a then where you invoke your service method, you need to change that to a subscribe, which is essentially the equivalent version for Observables).

See this answer for a detailed explanation on how to properly catch exceptions while using Observables.

Upvotes: 0

Related Questions