2

At backend I have created a nice Exception mechanism so when a request fail. Server going to send a nice error message to client with some error code .

Like this:

@Getter
public class ErrorResponse {

    /**
     * Http Response status code
     */
    private final HttpStatus status;

    /**
     * General Error Message
     */
    private final String message;

    private final ErrorCode errorCode;

    private final Date timeStamp;
...
}

I want to show error messages to user by default for each fail.

I have tried to extend HttpClient

public get<T>(endPoint: string, options?: IRequestOptions): Observable<T> {
    return this.http.get<T>(this.API + endPoint, options);
  }

But it's returning an Observable

In most of page I am doing something like this.:

this.client.post(WebUtils.RESOURCE_HOST + '/api' + '/actor/create', formData
    ).subscribe(
      () => this.onSuccessfulPost(),
      error => {
        this.snack.error(error.error.message);
      }
    );

In a lot of pages I am writing the same thing :

error => {
            this.snack.error(error.error.message);
          }

I read this post which about extending HttpClient.
But it is not enough for me it's only defining a default "API_HOST" I want to define default error function for request methods return objects and they are Observables.

Is there anyway to manipulate returning object of "HttpClient Request Methods" like extending?

1
  • 1
    If you use NgRx library, everthing will be centralized not only error handling. Or you can build your own light store instead of NgRx. Additionally check this post for global error handling in angular. medium.com/@amcdnl/… Commented Jul 26, 2018 at 12:46

3 Answers 3

3

You can use the new HTTPClient interceptors that are made for that.

Here is an example of one :

export class ErrorHandlerService implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next
      .handle(req)
      .catch((err: HttpErrorResponse) => {
          console.log('error');
          // Mandatory return statement
          return Observable.throw(err);
        }
      );
  }

}

At every HTTP request performed by Angular, this interceptor will be ran, and will behave the way you tell it to do. In this case, it will log the error, but you can make him do whatever you want.

Sign up to request clarification or add additional context in comments.

1 Comment

To the people who downvote, have the decency to comment why you downvoted. This is coming straight from the documentation.
1

what I personally do to centralize error handling, is the following:

In my Service, I intercept the http Requests with catchError like

return this.httpClient .get(...) .pipe( catchError(this.handleError.bind(this) );

The error handling (in my case, logging dependent of the HTTP return status and the return value) is done in the handleError method like this:

`

private handleError(error: any) {
    error = error || {};
    if (error.status == 401 || error == 401 || error == 'Unauthorized') {
      ...
      this.logout();
    } else if (error.status == 403 || error == 403 || error == 'Forbidden') {
      ...
    } else if ((error.status == 423 || error == 423) && error._body) {
      ...
    } else if (error.status == 500) {
      ...
    } else {
      return this.processUnknownError(error);
    }
    return _throw(error);
  }

`

I also declared a global noop function

export function noop() {}

so that all my service consumers only call

this.dataService.getFoo().subscribe((values) => { ... }, noop);

Maybe that attempt is also suitable for you?

7 Comments

This is the old way.
Thank you Marcel. I think this can be work. If I can not found anything better than this is what I use. But I want to effect directly "HttpClient". For example I don't want to write error handlig for each data service. I want to leave empty err function. So the implementation should fill it by default. Maybe I am expecting too much :)
Hey again, if you want to use the handleError-Function in multiple Services, just put it in a seperate ts file and import it in every service. After all, it's just a pure function and you can pass all parameter it needs from the services :)
@MuhammedOzdogan I don't know why you are ignoring my answer (and maybe downvoting it), this is from the way to go from the official documentation. This will allow you to write a single catch function and not one more.
This solution forces to make an import and write at least one line to every HTTP call you make. With an interceptor, you create only one file and you're done.
|
1

Thanks to trichetriche, If you want to make a centralized exception handling with "HttpClient" here is my final code:

1) Create a interceptor:

import {Injectable} from '@angular/core';
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable} from 'rxjs';
import {catchError} from 'rxjs/operators';
import {throwError} from 'rxjs';
import {SnackService} from '../services/snack.service';

@Injectable({
  providedIn: 'root'
})
export class HttpErrorHandlerService implements HttpInterceptor {

  constructor(private snack: SnackService) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req)
      .pipe(catchError(err => {
          this.snack.error(err.error.message);
          return throwError(err);
        }
      ));
  }

}

Snack is a customized snackbar with that I notify user.

2) Provide your interceptor:

const HTTP_INTERCEPTOR_PROVIDERS = [
  {provide: HTTP_INTERCEPTORS, useClass: HttpErrorHandlerService, multi: true }
];

Add this into your project module it can be "app.module.ts": providers: [HTTP_INTERCEPTOR_PROVIDERS]

Thats all. Now if any error occurs you can handle it in your interceptor.

And my request code blocks don't have any err function.

From this:

 this.httpClient.post('http://localhost:8080/api/auth/login', loginModel, httpOptions)
      .subscribe(
        result => {
          this.createToken(result);
        },
        (error) => {
          this.parseError(error);
        }
      );

To this:

 this.httpClient.post('http://localhost:8080/api/auth/login', loginModel, httpOptions)
      .subscribe(
        result => {
          this.createToken(result);
        }
      );

No more error function and that was I want.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.