Join my mailing list for more exclusive content and access to the archive of my private tips of the week: mobirony.ck.page/4a331b9076
@dsldsl64602 жыл бұрын
you can use combineLatest({a: obsa$, b: obsb$, c: obsc$}) instead of([obsa$, obsb$, obsc$]) and skip .pipe(map((a,b,c)=>({a,b,c})) to get the same result with cleaner code
@JoshuaMorony2 жыл бұрын
Thanks! Yeah I thought this was deprecated but discovered in another comment thread the deprecation warning in VS Code was not accurate
@uziboozy45402 жыл бұрын
@@JoshuaMorony use IntelliJ instead.
@namlevan2929 Жыл бұрын
Pro tip. Thanks
@ImperiumLibertas Жыл бұрын
@@uziboozy4540you mean neovim right?
@xocomil2 жыл бұрын
What a fantastic overview of RxJs. You taught so many beginner-friendly concepts with great examples. This video is on my list of things to share with new Angular devs.
@guzmanoj2 жыл бұрын
I've been doing this for a long time now with no complaints! ❤
@Szergej332 жыл бұрын
Very good overview, your videos have been really helpful lately. We use this pattern in my job, so if a new junior dev were to start, I could just share this to get them up to speed ^^ For trivial usages like this, wehre you have 3 streams, and you pipe-map them to themselves, you can also create the object inside the combineLatest operator. Instead of passing in an array of sources, you can do combineLatest( { source1name: this.source1$, source2name: this.source2$ } ) It does exactly the same thing, just a bit less verbose to type out. Furthermore, if in your pipe you do need to use the streams ot do some data manipulation, you can access those streams by key, instead of by an array index, without the map operator.
@JoshuaMorony2 жыл бұрын
Thanks! I have it in my head that usage is deprecated? I haven't really looked into it though so I'll play around with this and see if I like it better :)
@Szergej332 жыл бұрын
@@JoshuaMorony My comments keep getting deleted if I link the rxjs docs, KZbin thinks im a spam bot :D I thought the same, my IDE wrongly keeps suggesting that it is deprecated, while it is not. The old signature is deprecated, where you pass in multiple sources as multiple arguments. The Array and hte Object signatures are recommended. Same with the ForkJoin operator. // deprecated combineLatest(odd$, even$); // suggested change combineLatest([odd$, even$]); // or combineLatest({odd: odd$, even: even$})
@JoshuaMorony2 жыл бұрын
@@Szergej33 Thanks for the clarification! Yeah I get that deprecation warning in the IDE too which is a bit annoying (especially for teaching it)
@Tomas-ir8xl2 жыл бұрын
@@JoshuaMorony You can disable IDE deprecation check and use Es-Lint + eslint-plugin-deprecation instead.
@AlainBoudard2 жыл бұрын
But isn't that the whole CombineLatest operator deprecated, not only this signature ? Replaced with CombineLatestWith, says the doc ?
@cedi29292 жыл бұрын
I absolutely love your channel bro. Just started working as dev fulltime, grooving into Angular and RxJs with your vidoes. Big shoutout! ❤✌
@subashbarik2 жыл бұрын
Your videos are always helpful for a beginner like me in Angular.
@CaseAhr2 жыл бұрын
So simple, but so valuable. You help me so much with wrapping my head around this stuff. Thank you for keeping you examples relatively simple.
@yzzygomez Жыл бұрын
This is gold. Thanks mate!
@shivisuper912 жыл бұрын
This is quality content! Glad i found this channel
@BarrettGamingHD Жыл бұрын
Awesome. I never knew about ignoreElements, I needed to know something like this existed for work!
@AlainBoudard2 жыл бұрын
Another great video Josh ! I find the straight declaration > instanciation very nice, because sometimes TS compiler gives us hard time declaring the proper type when using Observables with all the possible undefined outputs.
@MarcoPinheiro2 жыл бұрын
Really nice topic, thank you very much Joshua!
@dawidos00952 жыл бұрын
Great content, especially in these days when almost everyone claims that angular is dead etc. Keep up the good work! 💪
@billy84612 жыл бұрын
really liked this approach. I had on of the observables emitting another observable so i usetd startWith(of({})) Thanks
@jaybee638210 ай бұрын
The *ngrxLet directive is a lifesaver.
@NerdENerd Жыл бұрын
I prefer the patten because it is an object it is always true and because the properties are using the async pipe they are null before emitting. Much cleaner in my opinion.
@adambickford8720 Жыл бұрын
You are losing control over your concurrency as nothing is coordinating those subs. You're putting a lot of TS in the template which is a poor separation of concerns. You're also exposing a lot more of your class internals which promotes coupling. You could literally emit that exact struct from a Subject with a default value. I think this is worse in every way :shrug:
@indiasnumber1architect5742 жыл бұрын
do more of this!! this is amazing
@slinkyfoxx2 жыл бұрын
These videos are outstanding
@LucidFabrics2 жыл бұрын
I , at this verry moment, will be refactoring a page that receives a separate set of streams from multiple api calls into one stream and then display the a skeleton-text using only one condition. That will be fun. thanks for sharing!
@mahmoudlawendy60292 жыл бұрын
Thanks for explaining it really well! I've been putting off learning soft soft cuz it looks so intimidating but now that I easily understood the
@sergiokagiema9658 Жыл бұрын
Great job man!
@OLIV3R_YT2 жыл бұрын
Awesome video as always
@julienwickramatunga73382 жыл бұрын
Nice pattern, thank you very much!
@alextiger5482 жыл бұрын
thanks man, good stuff.! One of the best
@stepyCS22 жыл бұрын
Love your vids! Keep it up brotha
@vladimirlebedev000102 жыл бұрын
Thank you! Your content is very useful, keep uploading videos! :)
@SuperAussi32 жыл бұрын
Thanks a lot...very good videos
@maks-yaremenko2 жыл бұрын
very useful as always! thanks
@LarsRyeJeppesen2 жыл бұрын
I do the same, rxjs is so awesome
@RyanWaite28 Жыл бұрын
This is actually smart
@rd_45 Жыл бұрын
Thanks josh
@angeltemelko65442 жыл бұрын
Awesome content!
@StephenMoreira2 жыл бұрын
Very informative.
@dmitriysahno23628 ай бұрын
Great! 👍
@plsreleasethekraken Жыл бұрын
Does using Reactive Forms for large form views change this approach? I generally just subscribe to my data from persisted storage and then set the reactive form data imperatively. At that point Reactive Forms is binding the view and model data.
@praveensripati34072 жыл бұрын
learned new things, Very informative. @Joshua Morony Can you make videos regarding forms and how to handle them in an efficient way, it would be really helpful, Thanks✌.
@gautamfitness43142 жыл бұрын
Can u teach how to use nexus
@muzammiliqbal17532 жыл бұрын
Nice thing but the issue I believe with this approach would be if we use shareReplay for multiple subscriptions then firstly, we will have to trigger subscription again if we want to update data of template after let's say deleting some record. Secondly, we will have to call checkError again. There are solutions to this like a refresh subject in order to forcefully get data again but in the end there will be too many observeables for a basic thing.
@JoshuaMorony2 жыл бұрын
Do you have an example of what you mean? There shouldn't be any issues with needing to fetch data again as that's the point of using the observable streams - we aren't pulling data out of the streams to put into our vm, the entire vm is composed of streams that will update when necessary.
@behindthescenex2 жыл бұрын
Hi Joshua! Thankyou for sharing this video. If i may ask, can you sometime covering how to unit test with this kind reactive pattern? Thankyou so much before 🙏
@JoshuaMorony2 жыл бұрын
Yes not sure if I have any videos on this already, but a vid on observerSpy (which is what I mostly use to test all my observables) I think would be interesting
@romarioputra37752 жыл бұрын
So viewmodel design pattern is basically combine every observable into 1 right?
@JoshuaMorony2 жыл бұрын
The view model pattern is more general than just this specific context, but in general means creating some kind of object that has all of the values for your view. In this context, yes I am talking about combining everything into one observable stream that will emit the view model object.
@ventsi342 жыл бұрын
It looks very clean but I have a question. When this is better to be used than resolvers? I think it solves the same problem.
@JoshuaMorony2 жыл бұрын
I don't really ever use resolvers so maybe there is some interesting patterns I'm missing, but in my mind you would only use a resolver when you need to pre-fetch some data before navigating to the page.
@Qellson2 жыл бұрын
Great Job! Love your content! Just one question. Would it be better to use BehaviourSubjects with an initial value instead of combining Subjects with startWith operators?
@JoshuaMorony2 жыл бұрын
I might be missing your exact meaning but sure if you can set something up as a BehaviorSubject that makes sense, but otherwise if you are dealing with an async stream that doesn't have an initial value then startWith is a good way to deal with that
@SamiullahKhan2 жыл бұрын
Thanks for the work, ignoreElements are totally new for me. What do you think, what action user needs to take when there is error. Giving option of retry is one solution, is that possible vm$ stream? Or are there better solutios?
@JoshuaMorony2 жыл бұрын
Yeah there's a bunch of different things you can implement with streams, you can even implement automatic retries when there is an error (e.g. try making the same request to an API 3 times before finally giving up and erroring)
@joaomarques82552 жыл бұрын
Hi @Josua ! I really like this approach and it's a really nice pattern to have but don't we need to worry about performance? For example if I have a huge vm object and only one of the subject emmiting one value at some point this will cause the entire vm to emit that huge vm object with only one updated value. In other words, emmiting a entire object only because one subject emmited a value.
@JoshuaMorony2 жыл бұрын
This shouldn't effect the rendering of your component because, as far as I understand at least, even if the vm$ is emitting all of the values when any of them change, as long as you are using OnPush it will not trigger change detection for any components using those values as inputs (unless they have changed) as they maintain the same reference.
@valeron_1337 Жыл бұрын
I think of a use case which could potentially lead us to performance issue if we had some heavy computations inside of our derived vm$, especially if the vm$ itself was large. Thus for each emission inside combineLatest we would have to recompute everything again even though most of the output would evaluate to the same value as the previous one.
@tryhuma2 жыл бұрын
what about efficiency? one stream emission causes whole template rendering
@JoshuaMorony2 жыл бұрын
It won't - if you are using OnPush only the value that changes in the vm will trigger change detection where it is used as an input, and if you aren't using OnPush then change detection is triggered for your entire component tree on every change anyway. In both cases though, it's probably important to clarify that Angular won't re-render everything in the DOM anyway, just what has changed.
@nathanalberg2 жыл бұрын
using `vm$ = combineLatest` in webstorm is not giving me type information about the objects in the template atm... :(
@d.nickolas2 жыл бұрын
What is the difference between forkJoin and combineLatest?
@JoshuaMorony2 жыл бұрын
A forkJoin will wait for all of its input observables to complete and then emit an array containing all of their values - just once. combineLatest will emit every time there are new values, and the input observables may not necessarily complete.
@EditorialGuiasdelSur2 жыл бұрын
I would like to ask you a question please?
@tleveque2 жыл бұрын
Really cool Rxjs stuff here..... But I wonder, what is the advantage of this approach? It seams that it can get really complicated with a more complex case. If there is no performance improvement, I prefer to keep with more readable code to be easily maintainable. In the real world of software development, this is the key. "Maintainable". I always keep in mind what will happen if in 2 years from now, another developper has to go into this code to fix a bug or add a feature. He should be able to understand how the code is working really fast. And I don't think that kind of advance use of Rxjs is really helping.
@JoshuaMorony2 жыл бұрын
At least in my opinion, this makes things simpler. It makes it very explicit what data is intended to be displayed in the template, and there is one mechanism for doing that which will auto update the template as those values change. If you want to display something in the template, you add it to the vm$ stream. I think this provides a nice pattern/rule for many different devs to follow over time, rather than potentially different devs doing different things to display values in the template.
@ponderwonder2 жыл бұрын
It creates a nice separation of "template" vs "template logic". Conceptually, I start from the template. "What's do I need to know in order to render this view in all of the states we need to support, with the simplest interface?". Then I fetch all the things I'll need (usually from API services, user inputs etc) and compose those streams together, finally mapping the data to my simple VM. It prevents you from adding a property to an API interface somewhere and cascading that down into the template. It also means we can easily keep complex logic out of the template and in the TS instead. E.g. `*ngIf="user.firstName && user.lastName && user.loaded && user.whatever"` we can just do `*ngIf="user.name"` and move the logic into the observable map().
@valeron_1337 Жыл бұрын
@@ponderwonder I like your explanation. However, If the vw$ were more complex with more inputs to combineLatest and even more of these derived fields requiring additional pipeable operators to evaluate themselves (such as you described with map to obtain user.name) then I think we would still end up with pretty much the same mess as we never used vm$. In my opinion, the pattern in the video is very nice though it won't make much difference if we have to deal with bigger number of values inside the vm$. What are your thoughts @Peter Hodges @JoshuaMorony PS. Thanks for sharing this.
@ponderwonder Жыл бұрын
@@valeron_1337 Always welcome the discussion. I think I would argue the opposite to your logic. For very simple components that have a couple of angular inputs and a simple template, using the vm pattern can feel like overkill. And yeah, you can still keep template logic in the TS by using OnChanges to map to an internal property. As the number of inputs (general inputs, not necessarily angular inputs) increases, and especially where these inputs are asynchronous and can happen over time, the reactive nature of rxjs makes things much simpler. (Think DOM events, socket events, timers, polling etc.) Without it, it's really easy to get into inconsistent states due to race conditions, things happening in orders you didn't expect etc. With reactive programming, providing you've piped your streams together correctlt, you'll always get the correct result eventually. If a stream further up the chain emits out of sequence, or twice, unexpectedly, maybe the vm is emitted twice (a mistake) but you'll still end up with the correct result. The only time I've really seen it become a mess is where people combine reactive programming with imperative patterns (e.g. using a tap and updating a property on the class, or opening a dialog via a function invocation, rather than declaratively) but this is the vm pattern being applied incorrectly rather than a problem with the vm pattern itself.
@KrycekA2 жыл бұрын
Josh, excellent video as always! I am curious to hear what you think of the following approach as an alternative to your solution: In the template, you could use the following condition: *ngIf="{greeting: greeting$ | async, user: user$ | async, count: count$ | async} as vm". I used this approach a few times on my day job
@masterlup2 жыл бұрын
this is bad practice for multiple reasons: 1. make your template as lightweight and stupid as possible. Therefore its easier to change stuff in die future. 2. now you have 3 async pipes in the template vs 1 async pipe. This does not scale in terms of performance and also you're bloating your template what violates Nr1 again. Imagine you have 15 properties with your approach
@blokche_dev2 жыл бұрын
Still valuable content. Thanks a lot. You can also use an object in combineLatest if I am not mistaken. Maybe on the latest versions only? No need to map your value anymore. const fullname$ = combineLatest({ firstname: firstname$, lastname: lastname$ });
@masterlup2 жыл бұрын
this has been mentioned by dsl dsl one day earlier
@blokche_dev2 жыл бұрын
@@masterlup Did not notice. Sorry.
@klafbang Жыл бұрын
You do not answer the question from the title. You just show reasons it is a bad idea.
@masterlup2 жыл бұрын
rxAngular or ngrx component store
@LarsRyeJeppesen2 жыл бұрын
Ngrx
@DjLeonSKennedy Жыл бұрын
why are u using angular?
@kaibe5241 Жыл бұрын
What's the main benefit of this? It seems like an unnecessary step for accessing things you may already have access to.
@anj000 Жыл бұрын
8:10 not gona lie - coming from Vue this looks... horrible. I really want to start liking Angular, but such structures seem over engineered and hard to read.
@anj000 Жыл бұрын
It looks like solving problems, that we created in the first place. Not really getting the point of doing this.
@DawidRudzik Жыл бұрын
biggest mistake in rxjs is error handling catchError((err) => of (err)) is such common and such ugly solution that it's surprising that no one in rxjs team came up with the idea to donst complete Observale when errors appear. Observable should be complete only in explicity way using .complete() method. Observable should be stream of errors, and success. Alternatively inside constructor whe shuld have oportunity to configure that behavior: new Subject({errorCompleteSubject: true})
@petraveryanov25722 жыл бұрын
This example is so basic that I dont see any advantage of this approach. I mean with old-style 3x subscribe I gonna have pretty same html and js wont be more complicated either... And there are some questions, how this code will look like in more advanced, more real cases: E.g. lets say count$ is an input and user$ is http get with count$ as param -- can u deal this with no subscriptions in js. E.g. u need to calculate some value based on greeting$ and count$ -- where this code goes? If you add this to combineLatest thing, then its gonna run also when userDelayed$ is emitted. etc.
@JoshuaMorony2 жыл бұрын
Coding reactively is a bit of a different mental model, but the general idea for the scenarios you have suggested is to derive streams in some manner using RxJS operators for whatever you want to add to the vm$ stream. For your count->user example you would have a user$ stream that is derived from the count$ stream and switchMaps to http. For greeting + count you would create a new stream with combineLatest that has both of those streams as input, then use the map operator (or whatever other operator you need) to get the result you want. All of these streams you create go into the single vm$ stream, and yes any time any of the input streams change the vm$ stream will emit all of the values, but this doesn't matter. If you are using these vm$ stream values as inputs to components the reference is maintained if the value has not actually changed, so you aren't unnecessarily triggering change detection for unchanged values.
@josepalacid Жыл бұрын
Too much screen blank or useless code space wasted that could leave place to a bigger font. Mobile and vision impaired subscribers will be grateful.