Тёмный

How to handle errors REACTIVELY with the async pipe 

Joshua Morony
Подписаться 73 тыс.
Просмотров 17 тыс.
50% 1

My modern Angular course: angularstart.com/
In this video, we take a look at how to handle errors from RxJS observable streams reactively when using the async pipe in Angular.
Get weekly content and tips exclusive to my newsletter: mobirony.ck.page/4a331b9076
Learn Angular with Ionic: ionicstart.com
Previous video: • How to use the ASYNC P...
Source code: github.com/joshuamorony/async...
0:00 Introduction
1:38 The problem
2:54 Basic error handling
4:41 Using a view model
6:29 Multiple values
7:47 Conclusion
#angular #rxjs #ionic
- More tutorials: eliteionic.com
- Follow me on Twitter: / joshuamorony

Опубликовано:

 

1 июн 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 46   
@JoshuaMorony
@JoshuaMorony 10 месяцев назад
Join my mailing list for more exclusive content and access to the archive of my private tips of the week: mobirony.ck.page/4a331b9076
@Fyasco_AlanChoufa
@Fyasco_AlanChoufa 2 года назад
Separate streams.. so simple and so reactive ! Love this !
@KamelJabber1
@KamelJabber1 2 года назад
I've been hooked on your videos lately, thanks! Good stuff!
@beeman-dev
@beeman-dev 2 года назад
Awesome stuff Josh 🙌
@RobertLejeuneQc
@RobertLejeuneQc 2 года назад
Really helpful, thank you for sharing!
@tommclellan
@tommclellan 2 года назад
Great stuff, thanks for this example!
@diehypotenuse4908
@diehypotenuse4908 Год назад
solved my daily evening problems in 15 minutes. thats awesome
@coreytollerud7298
@coreytollerud7298 Год назад
Assuming cold observables, doesn't using both user$ and userError$ in the view cause two subscriptions to user$ (i.e. maybe double-fetching data from the server?)
@cheatman05
@cheatman05 11 месяцев назад
As a temporary workaround, you can use the shareReplay(1) operator in the pipe of the original source to avoid triggering the cold observable each time a subscription occurs.
@slimbofat
@slimbofat 11 месяцев назад
@@cheatman05 yep agreed (as long as you remember to also enable refCount as well). This video's advice can be used effectively with multicast observables, but I imagine that this video has led a lot of people down a painful, confusing path since it came out.
2 года назад
Great video, thanks!
@danlevy9478
@danlevy9478 Год назад
great stuff, love your videos
@captain_knoxx
@captain_knoxx 2 года назад
really helpful!
@JoshuaMorony
@JoshuaMorony 2 года назад
EDIT: I've added an example of how you would handle an API/Http request with this approach in the source code: github.com/joshuamorony/async-error-handling/blob/main/src/app/shared/data-access/user/user.service.ts Pinning my response to another comment here because it's an important concept that my dummy observables aren't highlighting: "by default there would be two separate requests if we were making a GET request. So if you were hitting an API with an Http request I would make sure to have the service (e.g. from the getUser method) set up a hot observable (e.g. cache the observable stream using a class member in the service, and use shareReplay) - this way both streams would share the same data emissions and the GET request would only be performed once." I have another tutorial on caching/sharing observables here: ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-H542ZSyubrE.html
@Matrium0
@Matrium0 Год назад
Thanks for the example. Usually everyone is praising async pipe, without showing error handling AT ALL. I got to say I am not really convinced though. It's just so BLOATED and easy to get wrong (like if you forgot the shareReplay and fire multiple requests). Your github example has like 35 codes dedicated to just handling one simple async function and it's potential errors. I'd rather subscribe manually and handle next and error myself, that's like 10 lines of code AT MOST and pretty much zero room to fuck up. Also seems so much more more readable - though I get that a declarative coding die-hard might drop dead from shock when seeing such blasphemy :)
@slimbofat
@slimbofat 10 месяцев назад
@@Matrium0 I'm not a fan of this strategy (tons of foot guns) , and I agree in isolation a subscription isn't a big deal... until you have like 10 of them and they start having short transient lifetimes... at which point congrats you've reinvented callback hell
@codeSurvivor
@codeSurvivor 6 месяцев назад
Signals to the rescue
@rafiquemohammed3029
@rafiquemohammed3029 Год назад
Alternatively you can simply combine all the observables and use it as a vm$ . for ex: const vm$=combineLatest(obs1,obs2, ...obsN) and in html to keep more clean and readable
@codeSurvivor
@codeSurvivor 6 месяцев назад
Hi! I think this would not be the same since combineLatest won't emit until all the streams it contains emit, therefore the template in the video should be changed, and the logic can become not so clear. You could add startWith(null) for each of the combineLatests streams to have exactly the same behavior, though
@wangguanghui3067
@wangguanghui3067 Год назад
Great video! I wonder if it's possible to extract this loading error and data pieces in a reusable component? The data is projected into ng-content so we can focus on the data.
@reidyoung298
@reidyoung298 Год назад
A util function or error handling service could do this nicely for you
@shemmuthanga6352
@shemmuthanga6352 2 года назад
Great approach, Josh. Could you make a follow up video showing how one can update the data e.g deleting/adding an item in an array, pagination. Thanks
@JoshuaMorony
@JoshuaMorony 2 года назад
Is there some specific problem you face in regard to this? Let's say the getUser method is actually a getList method that returns a stream of an array of items that we display in the template. If we wanted to add an item then we would just do something like call addItem which would handle adding the item in the service, and then cause the getList method to emit the new data on that stream, which will then be picked up by the subscription we already have.
@shemmuthanga6352
@shemmuthanga6352 2 года назад
@@JoshuaMorony Right. That makes sense. Especially if you are using a state management lib or the (Behaviour)Subject pattern. My approach involved trying to append/delete to the response from within the template or component instead of emitting a new response from the observable in the service
@JoshuaMorony
@JoshuaMorony 2 года назад
@@shemmuthanga6352 Can you give me a specific scenario (e.g. you have an array of items, you are displaying that in the template, you want to add an item to the array - why is it that you want to add an item but not to the source observable/what do you want to do with it etc) and I might be able to give some advice on doing this in a reactive way :)
@shemmuthanga6352
@shemmuthanga6352 2 года назад
@@JoshuaMorony ​ OK. Let's say you have an api which you pass a number to fetch paginated data. e.g /api/posts/1. Page 2 will be /api/posts/2, etc. Page 1 will be initialised in the ngOnInit hook . How would you fetch and append the next page results, reactively :) e.g through infinite scroll event or button click. The response for each request will be something like {success: boolean, results: [posts] }. I hope I am comprehensible enough.
@JoshuaMorony
@JoshuaMorony 2 года назад
@@shemmuthanga6352 Cool that makes sense - so in this case what you would want is a stream of that page number changing. Maybe you have a reactive form set up to handle the page input and then you utilise the valueChanges stream for that input. That will be the stream you subscribe to with the async pipe in the template, but of course we don't want to display the page number we want to display the data for that page number. So you pipe on a switchMap operator to that valueChanges stream - this will allow you to take the value from valueChanges, but pass it into a new observable stream instead. You would have the switchMap operator return the observable stream from the http request that fetches the data from the API (and that switchMap operator will have access to that page value from the original stream). Now every time the page number changes, your stream will emit the new page data. This probably would make a good video so maybe I'll do it!
@lautarobernati2557
@lautarobernati2557 10 месяцев назад
Couldn't you just mutate the original observable with the throwError function and return an empty response, so that the original observable doesn't error out, and the async pipe doesn't break? Rather than managing errors on a separate observable? Great video anyway
@Dorchwoods
@Dorchwoods Год назад
To add to this, in the app I'm working on, the card could have 4 states: success state (showing data), a loading state, the error state, and......an empty state. So basically showing some sort of graphic and a message that says 'No users' if !users.length. Thoughts on how to best handle that? I've never found a good, clean way of handling that without bringing in NGRX, which most of the time is overkill on small applications
@JoshuaMorony
@JoshuaMorony Год назад
I use NgRx Component Store for these sorts of scenarios - if you're not familiar with Component Store specifically it is a much more lightweight solution than the full NgRx Store. I have a video on doing pretty much this scenario here: ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-gYzAhW_glqc.html
@leonardopillay4200
@leonardopillay4200 2 года назад
Hi there i love your videos. Can you do an implementation of a login screen with a ion menu and nested routing in an application
@TayambaMwanza
@TayambaMwanza 2 года назад
Genius
@ttma1046
@ttma1046 2 года назад
is this two async on the same stream?which means subscribing on the same stream twice?
@JoshuaMorony
@JoshuaMorony 2 года назад
There are two separate streams: user$ and userError$ and they are each being subscribed to once.
@ytamb01
@ytamb01 2 года назад
@@JoshuaMorony if these were http requests would there just be one http request for each user even though there are two streams/subscriptions?
@JoshuaMorony
@JoshuaMorony 2 года назад
@@ytamb01 this is a good point to bring up - by default there would be two separate requests. So if you were getting an API with an Http request I would make sure to have the service (e.g. from the getUser method) set up a hot observable (e.g. cache the observable stream using a class member in the service, and use shareReplay) - this way both streams would share the same data emissions and the GET request would only be performed once.
@ytamb01
@ytamb01 2 года назад
@@JoshuaMorony Thanks. I'm never sure when sharing streams has this effect without watching the network tab!
@JoboyJordan
@JoboyJordan Год назад
@joshua morony, how would you cache the observable if there's an input paramter to getUser like userId?
@pauleth
@pauleth 2 года назад
lol metamask
@natqe4049
@natqe4049 2 года назад
shareReply instead of vm
@JoshuaMorony
@JoshuaMorony 2 года назад
Is there a particular reason you prefer shareReplay in this instance instead of creating a vm? shareReplay would deal with the issue of creating multiple subscriptions, but what I like about the vm is that I can just use the async pipe in one place rather than having to use it every time I want to use the value (just from a syntactic perspective).
@natqe4049
@natqe4049 2 года назад
@@JoshuaMorony shareReply is straight forward. vm looks like a hack and need explanation, it isn’t understandable when reviewing the code
@JoshuaMorony
@JoshuaMorony 2 года назад
@@natqe4049 thanks for your perspective, I do disagree on it being a hack though. Using a vm is a pretty common Angular pattern, and I'm creating it directly in the template here but you can also just create a single separate vm$ observable in the class to clean the template up even more.
@nickolaizein7465
@nickolaizein7465 Год назад
@@JoshuaMorony Hello! Can you show how vm$ can looks in this way ? In template I use now: *ngIf="{ channels: channels$ | async, error: channelsError$ | async } as vm", so if I understand correctly it can be just: *ngIf=" (vm$ | async) as vm" ? But I dont understand how to build vm$ in class in this case. Thanks!
Далее
Why I use a view model stream for my Angular templates
15:11
ngTemplateOutlet is WAY more useful than I realised
16:36
She’s Giving Birth in Class…?
00:21
Просмотров 5 млн
Error Handling with Observables
10:19
Просмотров 5 тыс.
The easier way to code Angular apps
9:54
Просмотров 63 тыс.
The mindset you need for a DECLARATIVE code refactor
7:56
RxJS Top Ten - Code This, Not That
14:44
Просмотров 251 тыс.