Handling HTTP errors - lordoftheflies/angular-essential-training GitHub Wiki

It's possible that HTTP calls may result in an error. From a service that is temporarily down to a malformed request or response, or even an error code in the response payload. Let's take a look at some code that we can add to handle errors that come through the calls we make with the HttpClient service. In the media-item.service.ts file. This code contains calls to the HTTP service, get, post and delete methods. These return an observable, and in the case of the get call, we have the use of the pipe method to apply an RxJS operator named map for extracting the media items from the response payload. The RxJS library provides an operator named catchError, that can be used to identify when the observable emits an error and if so, allows you to run a function to take some sort of action. We can make use of the catchError RxJS operator here by adding catchError to the import statement for rxjs/operators. And then down in the pipe method from the HTTP get call, after the map operator, we can add a comma and then a call to catchError. The catchError operator takes in a function that will be run if the observable emits an error. Let's set up a private class function for that and name it handleError. And for the parameter, let's set up one named error and use some TypeScript to specify the type with a colon and then HttpErrorResponse. The HttpClient observables will emit an error that contains an item of type HttpErrorResponse, thus we can use that type here. We need to include that in the imports list up top. And that comes from @angular/common/http. So let's add HttpErrorResponse to that. In the body of the handleError function, let's add a console.log here, so we can get some visual reporting of an error occurring. We can pass that error.message, which will contain the error summary in string form. Then in the catchError call, we can pass the class function with the syntax, this.handleError without the parentheses, because we don't want to call the function here, we just want to pass the reference to it. So with this code set up, if the HTTP call results in an error, any type of error, this console.log will run. That's good for some development debugging, but ideally we will want to notify the end user in some way. And we probably don't want to display the error message to the end user because it will be very technical. But we still want this function to have the observable emit an error. So the subscribed call to it from our components will know that an error occurred. The RxJS library provides a function called throwError that will create an observable that will immediately emit an error. And it can take in an argument that can contain the details of the error. So we can use that from within the handleError function to take care of the logic we want. We need to import that from rxjs, and that comes from the main rxjs module. So up in the import section, let's add import throwError from rxjs, and then in the handleError function, after the console.log call, let's add a return statement since we want to return the observable that this throwError creates. Then we can call throwError and pass it a generic error message that can be used to notify the end user of a problem. How about, "A data error occurred, please try again." So that covers the get call, but we really want to handle errors in the post and delete calls as well. We can do that in this class by reusing the handleError method in the post and delete observable configurations. Let's add a call .pipe off of the post method call and hand that the catchError operator call with the argument of this.handleError. And then do the same thing on the delete call. With that we have some error handling written in the MediaItemService class to give us a way to debug HTTP calls and to emit out a friendly message that can be used by components for display to the end user.