Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Angular - Error Handling 101

Tags: error

Posted on Jul 30 In an Angular app, we can handle errors in many ways, each with its pros and cons: let's explore them.The most common case of Error is an HTTP call gone bad. We may act upon it in different ways: we could either react to it, replace a value, or do nothing at all. And if we want to recover, where should we do it? At the component level, in a service, in a store...?First things first. When there's a HTTP error, Angular wraps it in a class called HttpErrorResponse: this happens both when the error is server-side (eg. a 500 error) and when the client makes a wrong request.These are just some fields of the class:This structure is thrown as an error on the Observable you subscribe to in order to start the request. You can then use these properties to understand the error type: for example, you can look at status to check if the user's session has expired!But what options do we have to recover from an error?Since the HttpClient service returns an Observable for each call, we can easily use RxJS operators.You can use retry in order to repeat the call if it errors out. You can even specify a maximum number of times:Instead of a number, you can supply a more powerful configuration object:With this, you can even delay the re-subscription (by a number of milliseconds, or when another Observable emits something), and tell whether the error count should be reset when a value is emitted.Speaking of HTTP requests, I cannot but recall the existence of a timeout operator, which does the opposite of what we want: it triggers an error, if the Observable doesn't emit in N milliseconds. It can come in handy together with retry or other operators.Another useful operator is catchError. This one may seem a bit strange at first, but that's because it's very flexible. Let me explain.When an Observable errors out, it stops completely. It cannot emit anything else, its life ends. The only way to get new values out of it is to subscribe again, restarting its execution.For this reason, this operator doesn't simply let you replace the error with a value: instead, it lets you switch to a new Observable in order to continue its life.For example, you may want to perform an additional HTTP request (a different one, otherwise you could simply use retry):But if this is too much, you can just return a value and that's it. The Observable will replace the error with the supplied value and then complete. You can supply the value by wrapping it in an Observable:Or, if you don't want to use the of operator, you could wrap it in an array:This works because every RxJS operator which accepts an Observable also accepts arrays, promises and iterators (they're called ObservableInput). They're all converted under the hood to an Observable.Now let's ask ourselves: where should we handle the errors?The first place to consider is the simplest, inside the subscribe. This usually happens inside Components. Something like this:This way, we can handle the errors in a very specific way, for example showing different errors based on the HTTP call or the page that the visitor is seeing.At the same time, it's also a bit verbose, but it obviously depends on how many errors we want to intercept. But one thing must be clear: we're not remedying the situation! We're just detecting the error. If we wanted to recover from the error, we should use the operators we talked about earlier, for example catchError.So, always remember this important difference: when we use catchError, we don't receive the error in the subscribe anymore.If you're using Services in your app (you probably should), you may also catch the errors there, before being delivered to the Components. Something like this:This code, however, has a problem: as we said, the Component will never know what's happened. So, for most cases, I don't recommend this approach: as the app grows, the need to show different error messages based on the page will also grow. With this technique, we cannot do that.Instead, consider using Services but also catching the errors at the component level:But if you also wanted to catch the errors at the Service level, you could use the tap operator to intercept the errors (but letting them be delivered to the components):This is not something I'd do normally, but it may be useful in some situations.You can also handle HTTP errors globally with an Interceptor. Interceptors let you do stuff before and after each HTTP request in your app. This example uses the new syntax for functional interceptors:You can then provide the interceptor globally like this:Be careful, though: don't catch the error, otherwise it won't be propagated to components! Instead, you may want to use this technique to handle some global state (eg. the number of ongoing requests, the total number of errors...). You could however catch the errors which shouldn't be seen by the components, for example with retry you could hide the request gone bad to the user. Interceptors are especially useful with 401 errors, signaling that the user's session has expired. This should cause a redirect to the login screen:Other common use-cases for interceptors are:If you're using a Store, you usually put your side-effects somewhere specific: I'll make an example with NgRx. If you're using a Store, it means that you're putting your data there instead of putting it inside the Components. This means that catching the errors inside an Effect is perfectly fine, and you may save the errors inside the Store directly.You may also want to group different error actions together and react to multiple errors in the same place:This is not something I'd suggest for the entire app (you'd be constantly updating it with dozens of actions) but for small sections of it (or pages) it should be totally fine.Finally, if you don't want to remedy but just detect the errors, you can implement your own ErrorHandler by replacing the default one in Angular:And provide it globally:This class intercepts all the unhandled errors in your app (not just HTTP errors but any error), it's the final place to consider for when you can't do anything to it. It's often useful for logging (eg. sending the error to an Analytics-like server). Of course, if you catch an error anywhere in your app (eg. with catchError), it won't end up here.Photo by Sarah Kilian on UnsplashTemplates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well Confirm For further actions, you may consider blocking this person and/or reporting abuse MohammedFarhoud - Mar 30 Rubens Lyra - Mar 29 Sandeep - Mar 18 Armen Vardanyan - Mar 27 Read our welcome letter which is an open invitation for you to join. Once suspended, this-is-angular will not be able to comment or publish posts until their suspension is removed. Once unsuspended, this-is-angular will be able to comment and publish posts again. Once unpublished, all posts by this-is-angular will become hidden and only accessible to themselves. If this-is-angular is not suspended, they can still re-publish their posts from their dashboard. Note: Once unpublished, this post will become invisible to the public and only accessible to Michele Stieven. They can still re-publish the post if they are not suspended. Thanks for keeping DEV Community safe. Here is what you can do to flag this-is-angular: this-is-angular consistently posts content that violates DEV Community's code of conduct because it is harassing, offensive or spammy. Unflagging this-is-angular will restore default visibility to their posts. DEV Community — A constructive and inclusive social network for software developers. With you every step of your journey. Built on Forem — the open source software that powers DEV and other inclusive communities.Made with love and Ruby on Rails. DEV Community © 2016 - 2023. We're a place where coders share, stay up-to-date and grow their careers.



This post first appeared on VedVyas Articles, please read the originial post: here

Share the post

Angular - Error Handling 101

×

Subscribe to Vedvyas Articles

Get updates delivered right to your inbox!

Thank you for your subscription

×