3

I am building an angular application which implements a custom error handler.

When you have a custom error handler and When an observable is used with http and when the errors are not caught, using a catch block, like following

this.http.get('/doesntExist').subscribe();

custom ErrorHandler's handleError() function gets a HttpErrorResponse object which can be used to get the necessary info and handle the error globally. But when you use a promise, like following

this.http.get('/doesntExist').toPromise();

instead of HttpErrorResponse , a string will be thrown saying

Error: Uncaught (in promise): HttpErrorResponse:

and you cannot really get the error info in the handleError() method. You can see it in action Here

Is it desired behavior ? Am i doing something wrong? Is there any workaround for this ? Please help. I am stuck;

Update

Stack trace of the string error in the console

Error: Uncaught (in promise): HttpErrorResponse: {"headers":{"normalizedNames":[],"lazyUpdate":null},"status":200,"statusText":"OK","url":"https://angular-promise-bug.stackblitz.io/doesntExist","ok":false,"name":"HttpErrorResponse","message":"Http failure during parsing for https://angular-promise-bug.stackblitz.io/doesntExist","error":{"error":{},"text":"<!DOCTYPE html>\n<html>\n<head>\n  <link href=\"https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700|Lato:400,700,900\" rel=\"stylesheet\">\n  <base href=\"/\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\" />\n  <link rel=\"stylesheet\" media=\"screen\" href=\"https://c.staticblitz.com/assets/preview-8222014a50f8588c56d057621cdaf871.css\" />\n  <script src=\"https://c.staticblitz.com/assets/common-bd7eff1ca58185bf8131b.js\" crossorigin=\"anonymous\"></script>\n  <script src=\"https://c.staticblitz.com/assets/ext-fb68da629568861fd08cb.js\" crossorigin=\"anonymous\"></script>\n  <script src=\"https://c.staticblitz.com/d/webcontainer.a966dcc4085d3fff5bb.js\" crossorigin=\"anonymous\"></script>\n  <script src=\"https://c.staticblitz.com/assets/preview-3a0c9433aa42f56dbd90b.js\" crossorigin=\"anonymous\"></script>\n  <script>(function(){_preboot(\"https://l.staticblitz.com/b/v1/angular-promise-bug/f9f42b37e9b\",{p:\"stackblitz\",a:\"AIzaSyBZSvuCzbUhuRrSps-HjM5bFClLPaFF9Vg\",o:true})})()</script>\n</head>\n<body></body>\n</html>\n"}}
    at resolvePromise (angular-promise-bug.stackblitz.io/turbo_modules/zone.js@0.8.26/dist/zone.js:814)
    at eval (angular-promise-bug.stackblitz.io/turbo_modules/zone.js@0.8.26/dist/zone.js:724)
    at SafeSubscriber.eval [as _error] (angular-promise-bug.stackblitz.io/turbo_modules/rxjs@6.3.3/internal/Observable.js:99)
    at SafeSubscriber.__tryOrUnsub (angular-promise-bug.stackblitz.io/turbo_modules/rxjs@6.3.3/internal/Subscriber.js:209)
    at SafeSubscriber.error (angular-promise-bug.stackblitz.io/turbo_modules/rxjs@6.3.3/internal/Subscriber.js:160)
    at Subscriber._error (angular-promise-bug.stackblitz.io/turbo_modules/rxjs@6.3.3/internal/Subscriber.js:93)
    at Subscriber.error (angular-promise-bug.stackblitz.io/turbo_modules/rxjs@6.3.3/internal/Subscriber.js:73)
    at MapSubscriber.Subscriber._error (angular-promise-bug.stackblitz.io/turbo_modules/rxjs@6.3.3/internal/Subscriber.js:93)
    at MapSubscriber.Subscriber.error (angular-promise-bug.stackblitz.io/turbo_modules/rxjs@6.3.3/internal/Subscriber.js:73)
    at FilterSubscriber.Subscriber._error (angular-promise-bug.stackblitz.io/turbo_modules/rxjs@6.3.3/internal/Subscriber.js:93)
Vikhyath Maiya
  • 3,122
  • 3
  • 34
  • 68

2 Answers2

7

error.rejection should get you the HttpErrorResponse when you use toPromise(). I tested following in the stackblitz

  handleError(error) {
    const zone = this.injector.get(NgZone);
    console.log('Here')
    console.log(error)

    if (!(error instanceof HttpErrorResponse)) {
      error = error.rejection;
    }
    console.log(error);
    alert('Open console to see the error')
  }
Aragorn
  • 5,021
  • 5
  • 26
  • 37
1

That's weird how Angular doesn't catch promise rejections in its global error handler. You could do this other approach as the top+accepted answer suggests here. Here's another hack

withPromise() {
      this.http.get('/doesntExist')
      .toPromise()
      .then(() => {})
      .catch((error) => {
       const errorSub = throwError (error);
       errorSub.subscribe();
      });
  }

You basically create a Observable and subscribe to it and let Angular handle the error. But again, that's a long way to do things as you already have an observable from the initial Http call.

Anjil Dhamala
  • 1,544
  • 3
  • 18
  • 37