Angular HttpClient error handling difficult

2020-07-30 01:00发布

问题:

The Angular documentation on the new HttpClient https://angular.io/guide/http has a section "Getting error details" where they show an example like below. I have modified to comments to document my observations which basic error classes end up where.

http
.get<ItemsResponse>('/api/items')
.subscribe(
  data => {...},
  (err: HttpErrorResponse) => {
    if (err.error instanceof Error) {
      // we never seem to get here
      console.log('An error occurred:', err.error.message);
    } else {
      // no network connection, HTTP404, HTTP500, HTTP200 & invalid JSON
      console.log(`Backend returned code ${err.status}, body was: ${err.error}`);
    }
  }
);

So at least 3 totally different categories of errors (network, http, response parsing) come in on a single channel and for each type one has to search for the actual reason in another part of HttpErrorResponse.

One can identify only one category, the HTTP errors through the standard error codes. But the other two types?

When I pull my network plug I get the extremely telling err.message = "Http failure response for (unknown url): 0 Unknown Error." Very descriptive.

When the new internal JSON parsing fails it says that there is a syntax error - but not at what position/character (as returned by JSON.parse()). See also here

What about other errors like timeouts, etc.?

Where can I find documentation on this? Has anyone figured out a way to generally analyse this so one can give meaningful messages to the user?

Angular 5.2 in Chrome on Win, Backend: ASP.NET4.6.1 pure IHttpHandler

回答1:

I had to look at the Angular source code to understand the possible error conditions. The error object will always be a HttpErrorResponse, but its error property may differ depending on the situation. Here's what can happen when using the default XHRBackend with the default responseType of 'json':

Response received with HTTP status code indicating error (not 200-299):

HttpErrorResponse.error will be the body parsed as JSON or if parsing fails, the body as text.

Response received with good HTTP status code (200-299), but body could not be parsed as JSON:

HttpErrorResponse.error will be an object typed as HttpJsonParseError with two properties:

  • error: the parse error (of type Error)
  • text: the body text

No response received due to an XHR network error:

HttpErrorResponse.error will be an XHR ProgressEvent with the type set to 'error'. (It may be wrongly typed as an ErrorEvent in older versions of TypeScript.)


Note: Angular does not set a timeout when making requests, nor does it register a timeout event handler. The default XHR timeout is 0, so requests will never time out client-side.



回答2:

This might help you

private handleError(err: HttpErrorResponse) {
    let errorMessage = '';
    if (err.error instanceof Error) {
        // A client-side or network error occurred. 
        errorMessage = `An error occurred: ${err.error.message}`;
    } else {
        // The backend returned an unsuccessful response code.
        // The response body may contain clues as to what went wrong,
        errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
    }
    console.error(errorMessage);
    return Observable.throw(errorMessage);
}