0

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.

Vojtech
  • 2,533
  • 9
  • 34
  • 65

3 Answers3

1

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.
    ...
}
Atul
  • 521
  • 1
  • 7
  • 20
0

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.

bugs
  • 14,631
  • 5
  • 48
  • 52
0
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);
        }););
mittal bhatt
  • 955
  • 6
  • 13