Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global Error handling with Observable.toPromise()

Hi i am using angular 5 and i am writing a global handler for the same which looks like following.

@Injectable()
export class ErrorsHandler implements ErrorHandler {
  constructor(
    private injector: Injector,
  ) { }


  handleError(error: Error | HttpErrorResponse) {
    const router = this.injector.get(Router);
    const zone = this.injector.get(NgZone);
    console.log('Here')
    console.log(error)

    if (error instanceof HttpErrorResponse) {

      // Client Error Happend
      zone.run(() => router.navigate(['/error'], { queryParams: { error: JSON.stringify(error) } }))

    } else {
      // Log the error anyway
      router.navigate(['/error'], { queryParams: { error: JSON.stringify({ message: 'Failed' }) } });
    }
  }
}

Everything works fine in Observable world ie if i do a failed http call like following

fireServerError() {
    this.httpService
            .get('https://jsonplaceholder.typicode.com/1')
            .subscribe(data => console.log('Data: ', data));
  }

and if the server call fails i get an error object properly as shown in the console image

enter image description here

But instead of that if i change it to a promise using toPromise(), like following

fireServerError() {
    this.httpService
            .get('https://jsonplaceholder.typicode.com/1')
            .toPromise();
  }

i get the following string stack trace instead of error Object itself

enter image description here

What am i doing wrong. How to throw/get the error object in case of unhandled promise rejections. Please help. I am stuck;

Please find the stackblitz link Here

like image 214
Vikhyath Maiya Avatar asked Dec 20 '18 13:12

Vikhyath Maiya


People also ask

How do you handle error in toPromise?

1 Answer. Show activity on this post. Once you use . toPromise() , you are essentially putting the behavior into a different execution context (read ECMAScript 10.4), which means that errors must be handled in/around the new execution context rather than having them bubble up in Angular like you are expecting.

How do you perform error handling in observable in Angular?

Angular CatchError is an RxJs Operator. We can use it to handle the errors thrown by the Angular Observable. Like all other RxJs operators, the CatchError also takes an observable as input and returns an observable (or throws an error).

How do you return an observable error?

We use the CatchError to handle the errors thrown by the Angular Observable. Once we handle the error, we must return an observable. We can either return a replacement observable or return an error. The observable returned from CatchError is immediately subscribed.

Where do you put CatchError?

Always put the “catchError” operator inside a switchMap (or similar) so that it only ends the API call stream and then returns the stream to the switchMap, which continues the Observable.


1 Answers

Once you use .toPromise(), you are essentially putting the behavior into a different execution context (read ECMAScript 10.4), which means that errors must be handled in/around the new execution context rather than having them bubble up in Angular like you are expecting.

I can't say I entirely follow your example code (is fireServerError always supposed to throw an error via an HTTP call?), but it seems like you want to try to execute promises without local error handling, but rather to have any error from a promise bubble up to the angular error handling. I'm not sure I'd recommend that, I believe it's best-practice to handle promise errors locally (i.e. using Promise.prototype.catch or a try/await/catch block when you create the promise).

That being said, error handling is of course a complicated topic and if you are dead set on just handling all errors at the global level then you can try using a global window event handler to catch all unhandled promise rejections and handle them there:

window.addEventListener("unhandledrejection", event => {
  event.preventDefault(); // prevent the default promise rejection behavior
  console.error(event); // do whatever you want with the error
}, false);

The MDN guide on promises may also help clear some things up, hope that helps!

like image 129
RocketMan Avatar answered Oct 13 '22 18:10

RocketMan