Lesson Description

The "Handling Stream Errors" Lesson is part of the full, Advanced Angular: Performance & Enterprise State course featured in this preview video. Here's what you'd learn in this lesson:

Alex shows how to handle RxJS errors using throwError and catchError, explaining how to keep observables running and where to place error handling in the pipeline.

Preview

Transcript from the "Handling Stream Errors" Lesson

[00:00:00]
>> Alex Okrushko: Now, RxJS has its own tricks. For example, let's get our event details back. Again, we're going to switch back to button clicks. So say instead of completing the transaction, I'm going to throw the error, so we're pretending. Ah, the error. And I'm going to change this and just go baby, it's getting 500 milliseconds. So say we have like soft map, for example, and we wanna throw error.

[00:00:42]
Throw error is got another operator within RxJS, it just throws error, but if you have a failed API request, it will do the same thing, it will just throw the error at you. And again, we just delayed by 500 milliseconds. But we also now we have the next channel, which is great, but let's see if we can do the error channel here. And the error, we have the error.

[00:01:23]
And we console.error, I know they just have the error itself. All right. So who knows what's going to happen. Take it to destroyed it all, yes. Because, it aired, it's kind of complete because it's there. That's a good, it's a good understanding, yes, so right now what happens is exhaust map will throw the air. And I'm going to read the error. And what happens after that because it was a coming through the error channel, this observable will basically, it's complete, right, so it's not even complete, it just won't listen for any new emissions, so let's just do it once.

[00:02:16]
Right, stream died. And that's it, even any further clicks won't do anything. Because that subscription is done. I'm like done done. OK, that's great. Um, but we can catch the error right before I go to this. We can catch the error, so in our pipeline, how about I catch the air, catch air. I can say, hey, I can't share and instead of that, I'll just have new cop.

[00:02:59]
I have, so catch error operator would start listening for the error channel and just catches that and replaces with the observable that is not fly. So how about now? What's going to happen now? Any guesses? Won't complete it won't complete because so we'll be basically caught in catching it all the time. Let's check that theory. So we do it once. Caught.

[00:03:43]
So we are in the happy path. Right? But let me click again. Oh, nothing's happening. Why nothing's happening is because it was listening for the, in the outer pipe, right, in the outer pipe, this is our outer pipe, it was listening for the error, and it's substituted for a single time emission observable, right? And that's it, it basically doesn't do anything after that because now I was listening for this one.

[00:04:13]
And this is just single time. So that's a little bit of a problem. So how can we solve this? And the way we can solve this is instead of having it in the outer pipe. Because the exhaust map on all the other maps, they are called also the flattening operators, they have flattened the observable from inside to the outside pipe. So if we catch this error before we flatten it, that is what it's going to help us.

[00:04:46]
So when we throw the error. And then instead of, here's the pipe, pipe delay here, that's great. And within this inner pipe, so we call this inner pipe, because it's within this, one of those flattening operators maps, exhaust map, we have this inner pipe here, and this is the outer pipe, right, this is the main line pipe. So if we catch the error here and can and return it before we flatten, we'll continue to listen for this new emissions.

[00:05:28]
Let's check this theory. It's caught, it's caught, so now it continues to listen to my clicks. This is, those issues are very hard to debug. And even if you test it, it's like, oh, I caught it, they error great. Now you're stopped listening for the new ones. That's why sometimes our RxJS is tricky. But again, for me, the value that these two provide is just enormous, these operators.

[00:05:57]
Four of them operators and the error catching handling logic that almost is required, it's no longer optional. It's almost required logic because otherwise your app stopped working. So having those two requirements basically having a choice to explicitly choose the strategy and explicitly handle the errors, very powerful, yes, so, um, I thought I heard the Angular team was trying to make RxJS an optional dependency, but you would say we're not at, or you probably are still going to want at least a little bit of RxJS for handling race conditions, for example, so, I agree with Angular team on this, and then, so we want to make any path that is more straightforward like signals now, right?

[00:06:55]
We have signals everywhere, right? Signals is a new reactive primitive that was basically replacing RxJS in a lot of places. And in this cases where it makes sense to have synchronous state, which is really awesome. Let's have, use it, let's leave RxJS for the tricky parts, and the tricky parts is usually asynchronous parts, and they usually race condition parts.

[00:07:28]
So, um, we've learned in the intermediate Angular, the HTTP resource, and right now, at least as of Angular 21, you cannot control the behavior of the HTTP resource. If you reload, if your signal that triggers HTTP resource changes, it cancels the previous one, so it basically acts as a switch map. And again, you cannot control that. They're using their abort signal inside and it's just the easiest way to do it without using RxJS for that, even though, they are using in their HTTP resource, they're using HTTP client, HTTP client depends on their RxJS, but within the resource, HTTP resource itself, they don't use any of those switch map, they really use abort signal to cancel the previous.

[00:08:29]
Um, yeah, so that's for me, I agree with that. This is where it becomes more interesting. And this would also lead to some of the design choices, and directs team made when we do the state management, which would be the next exercise. This actually wraps up this module, does anybody have questions? This is a tricky part, this is, but it's very important to understand these things.

[00:09:05]
Because it will drive a lot of our choices, especially how we handle state management. But it's more or less clear, right? Good. Chat is also clear. If a person if somebody wanted to decline a bunch of transactions. Even though, you know, let's say just one of them failed, so a batch type situation, which of those would you use for that scenario? Yeah, so which map you can do cool things with our RxJS insert and, so, you can have a little bit off topic, but you can definitely go into this, so you can switch map into an array, an array, and then an array, you'll merge map the array, which is a fan out of all the API requests, and then at the end, you will do two array, which combines all those values until the stream's complete, so all you're fanning out, you get aggregation, it's like almost promise all.

[00:10:06]
Right, how all the promises resolves when all the promises are resolved. So there's no magic bullet for that. You still have to use some sort of creativity with the array. It's fairly standard, but yes, you would use a combination of different RxJS operators to kind of achieve what you're talking about. But then, yeah, if you do it without RxJS again, you can do the promise all.

[00:10:35]
As well, right, um, or this, um, promise all will also fail if you do all the promises, but they'll be basically promise based approach, RxJS based approach or promise based approach, I'll be kind of the same in this case because you'll still have an array that you will map for every request for each item. I mean, there's always the API returning a, you know, a fail or a false boolean if something went wrong.

[00:10:59]
Mm-hmm. Um, and you want to ignore that, huh? You want to ignore that? No, OK. I don't. I, traditionally that's the way. So you would want to cancel all of them. Yeah, probably safer that way. It is, yes.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now