angularangular2-servicesangular2-http

Angular2: Service with http - handling errors (in 200 response)


So I am having a service that does some http API calls...

all the examples I've found online assume the JSON returned is valid...

what I want to do is to trigger the same call as catch block in http

so

getData(id: string): Observable<someEntity>{
    return this.http.get(someUrl)
        .map(this.handleResponse.bind(this))
        .catch(this.handleError);
}

private handleResponse(res: Response){
    if(res.status === 200){
        let body = res.text();
        if(!this.appService.IsJsonString(body)){
            return this.handleError(new Error('The response is not valid JSON '));
        }else{
            return res.json() || {};
        }
    }

}

private handleError (error: any) {
    this.appService.errorAdd(error.status, error.statusText, 'Error loading Index data', ErrorTypes.Data);

    let errMsg = (error.message) ? error.message : error.status ? `${error.status} - ${error.statusText}` : 'Server error';
    return Observable.throw(errMsg);
}

when I do then in my component:

this.myService.getData(someID)
    .subscribe(
        data => {...},
        error => {
            // LOGIC HERE
        }
    );

I want both errors to be handled by // LOGIC HERE (error block).... and not one in the success block and the other in error

What am I doing wrong?


Solution

  • Changing handleResponse as follow will meet your requirement.

    private handleResponse(res: Response){
        if(res.status === 200){
            let body = res.text();
            if(!this.appService.IsJsonString(body)){
    
                // Throw, instead of return
                throw 'The response is not valid JSON';
    
            }else{
                return res.json() || {};
            }
        }
    }
    

    You can also get rid of private handleError

    getData(id: string): Observable<someEntity>{
        return this.http.get(someUrl)
            .map(this.handleResponse.bind(this));
            // Don't catch here
            // Let the subscription error block to handle error throw
            // .catch(this.handleError);
    }
    

    If you want to hide RxJs object from component

    Change the way getData() is call

    getData(
        id: string,
        callback: (result: any) => void,
        errorHandler) {
    
        this.http.get(someUrl)
            .map(this.handleResponse.bind(this))
            .subscribe(r => callback(r), e=>errorHandler);
    }
    

    In component

    this.myService.getData(
        someID,
        data => {...},
        error => {
            // LOGIC HERE
        }
    );