Here is the playlist for the whole Angular Mistakes Series, enjoy 😉😊 ua-cam.com/video/3oq-gnDzz9k/v-deo.html Also, check out my courses at the Angular University, with content from Beginner to Advanced - angular-university.io
Thank you, I'm happy to hear that 😊. Yes, I feel the same, it's something that we need to get used to in the Angular world I feel. I've been developing more and more with Promises, they are super well supported in Angular, I'm very happy with the resulting code. 😊👍
When RxJs should be replaced by signals for sync stuff, it shouldn't be by promises for async problems because it adds so many tools out of the box. So yeah, in some cases, using promises might look "simplier", but by using RxJs you can keep everything declarative. Meaning it will be way simpler to add "bricks" to your observable, than it will be with classic promises. On top of that, you can share those observables way more easily by breaking your pipe into multiple intermediate observables. Also, if you compare both solutions, the RxJs one isn't really that more complex. The only extra thing to handle is the intermediate pipe to map into a tuple. for the next observable. Does this extra "complexity" will justify to chose promises instead of Observables ? I don't think so. The concatMap operator is what's translate the best your promise solution. But in many cases that's not the most performant one, mergeMap or switchMap are most of the case more suited and can do thing you can't do easily with promise (meaning it's out of the box, you don't have to add extra lines of code to cancel a request for example). About cancelation again : with a takeUntilDestroyed you can be sure that every heavy request are being canceled when you destroy your component. Thing that you can't do with promises without adding extra lines of code. You also have the power of the async pipe with Observable. Which makes things way easier to implement, because you don't need to use ngOnInit anymore, when you have to with promises. Small detail as well, in your RxJs example you are rethrowing the error when you don't in your promise one. So to conclude : yes in your example using promises looks easier / simpler. But by doing that, you decide to limit your options in the future. I would say simpler request takes less lines of code with promises, but the more your use becomes more complex, then RxJs will clearly improve the whole thing with well define pipes with very powerfull operators making the code easier to maintain in the long run. And it's reactive, which is a nice touch as well.
It's just an illusion, in general you gain nothing by using Observables for doing simple HTTP, and it's a lot less beginner-friendly. It drives away a lot of people from Angular. Other frameworks all use async / await for years, the added complexity is totally unnecessary in general. I know it's tough to accept, I've written myself code like that for years. 👍
@@AngularUniversity as I wrote in my first comment, it's way more powerful when you are doing more than simple cases. You want to retry ? You have a simple operator for that. You want to cache the data, same. You want to cancel things, idem. A denounce time ? Etc. Obviously you can do the same thing with promises. But you'll require more boilerplate for that. Plus observables are like Lego pieces that you can combine and reuse. Good luck to have the same thing with a promise approach. You are talking about other frameworks, but what about svelte where RxJs is also pushed by the team ? What about React and Vue that built their own abstraction on top of axios to handle cases like retry, caching, etc ? So let's agree that we disagree :D I'll keep writing 2/3 extra lines for small http requests. Because in the end, I'll write less on the entire code base.
@AngularUniversity, I apologize, but it seems there might be a misunderstanding in your example. The example provided appears to offer an inaccurate comparison. It's crucial to recognize that Observables are naturally cancelable, retryable, and cacheable, adhering to established community standards. It's also worth noting that using Observables in this example could optimize the code by avoiding unnecessary API calls when calling the save operation multiple times, poor internet connection, etc. It's somewhat ironic that your example suggests the opposite.
@@RodrigoSalesSilva There is no misunderstanding. Actually the example is not cancellable, but that's not the point. The point I was trying to make is that for 99.9% of HTTP code, all those Observable properties are not relevant. It's like trying to kill a mosquito with a canon. All other frameworks besides Angular HTTP using async /await, it works fine. The creator of Angular itself used async /await in it's new Qwik framework, the latest Angular official video tutorials show async / await. Observables are overkill for most if not all HTTP code, that is the main point of the video, I hope this helps clear things up. 👍
6 місяців тому+1
What if the result of the request is used in multiple components and services? How do you push these changes? Statemanagement with observables makes that easy.
Thank you, it's awesome to hear that 😊 Let me know if you have questions or concerns about Angular, I might just make a video with it, I'm always looking for new ideas. 😉
@@AngularUniversityI do have a doubt. Sometimes in projects I have to use ActivatedRoute to fetch params from the URL and then I need to call api requests the same way you did in the video. I cannot use firstvaluefrom(promise) in this case because my params are dynamic and paramMap is a never ending observable. So, how can I avoid Rxjs chaining in this scenario?
I think the initial problem you presented is just poor RXJS code. Ideally it should be something like this: // Function to make sequential requests getAllData(): Observable { return this.getLessons().pipe( switchMap((lessons) => this.getCourses(lessons)), switchMap((courses) => this.getUsers(courses)), catchError((error) => { console.error('Error in sequential requests:', error); return throwError(error); }) ); }
Using switchMap in this case doesn't change anything. This is still unnecessarily complex compared to using async/await, that's the main point I was trying to bring across. 👍
This makes so much sense. One question: if you are using NgRx for state management, would you then convert the final promise to an observable to process it in NgRx?
That is a great question, that is actually one of the places where I still use long chains of Observables at least for now, to write Ngrx Effects which I think is your use case too, right? In those cases, I tend nowadays to call an async/await service method, get back the promise and convert it to an Observable, if the logic that I'm trying to express is a good fit for Promises. I only use RxJs if I really have to, and it's been a breeze of fresh air for both me and my team, I feel we can get a lot more done. 😊 👍
For data fetching especially into a reactive store with effects etc, IMHO you should use observables all the way down to the angular http client, as that would allow things like switchmap etc to cancel the http requests. One disadvantage of using promises is you lose this cancellability and end up with zombie promises, wasteful work, wasteful network activity and possibly even race conditions depending on how your async code is structured. I agree with the thesis of this video but feel there are caveats and gotchas. Don't just blindly start converting a bunch of requests (especially simple queries) without taking stock of what you're losing in the process.
Yes Yes Yes Finally!! This is should be normalized among the community and everyone. The fact is that HTTP requests are async and can be used as promises is an underrated concept which is lost among the RxJs wave of tutorials. It is much simpler and clean though no one is aware of it. I remember one time I told someone about it and he was not believing that this is a true thing at all !! Hats off to @anularUniversity I believe we need more videos on this
Thank you, its awesome to hear that. 😊The crazy thing is, it's always been there from the beginning, a lots of projects use it. It's just not been mentioned a lot, but the feature is there if we need it, and it's a great alternative to RxJs for doing the most typical everyday async operations like HTTP 😊
Great example! This is how Angular should be done going forward. The first approach is ugly and should be avoided as much as possible! Keep up the good work with these series!
Thank you so much, I'm glad you are enjoying the videos. 😊 Yes I agree, if you want to save yourself and your team a world or unnecessary pain, consider switching to Promises when doing HTTP, it's a super natural fit. 👍😉
I'm starting to develop a new, large project. I am struggling with some architectural decisions... I am using almost all the new Angular features in this project, but the only feature I am not using at the moment is the new Signal API. I can't find a complete solution with Signals... I have always preferred to use promises for API requests (like in this video) and reserve Observables for intercepting requests (for authentication and loading, for example), emitting global states like session or notifications, and facilitating communication between unrelated components. I would love to get rid of zone.js in the near future for this project, but I don't exactly know how to architect my current app to align with that objective. Thank you for your videos.
Your approach sounds exactly like what I do nowadays, use async / await for HTTP and Observables for application-wide communication. 👍 Signals are still evolving, I think that the latest Signal API is already a good way to replace BehaviorSubject on shared services, so less RxJs is needed. 👍 When Signals are plugged into change detection, we will have a better idea how things will evolve in the future. If you want to make your application compatible with Zoneless in the future, might as well put all the data already inside signals. Btu I think there will be new signal primitive introduced to handle objects and automatically create a signal for each property recursively. There is ngRx Signal Store already for that, but I imagine there will be something similar at the level of the framework as it's such a fundamental primitive for signals. Iwouldn't put a top priority in getting rid of zones, they work very well and simplify development a lot, I really like them I think the developer experience is very good, i rarely run into any issue 😊 I can't predict the future, but there is a good chance that zones will still be very popular even after signals are here, unless the new way of doing signal-based components is super easy as well. Cheers and thank you for commenting 👍😊
@@AngularUniversity Hi Vasco. I have watched a lot of your university content - many thanks for the excellent content. You say we should use signals to go zoneless; can we not go zoneless using observables with async pipes? I also think toSignal is an inherently bad idea because you have to initialise it with a false value. What are your thoughts on this? I had a problem where I was initially calculating (in an effect) a default value for a form field when it was null. toSignal caused problems because the first argument it passed to the effect was the false value, meaning an incorrect default was calculated for the form field. I think toSignal can fool you into thinking you can turn an asynchronous source into a synchronous one without repercussions. As it stands I am never using toSignal again, which takes away a lot of the motivation for signals. Declarative rxjs + Angular is honestly absolutely beautiful and my favorite type of programming. It is painful for me to see the Angular team going in the opposite direction. I wish everybody could see how good it is and invest the time into learning it.
I think for http requests promises make more sense and appear cleaner in code. Do you have any recommendations for using promises in an OnInit? While it can be marked as async I think it will not wait for the results prior to the page load, so the behavior is a little unexpected and maybe undesirable?
It's amazing that you ask that, because I just finished recording minutes ago Mistake #4, where I cover just that. 😊 It's OK to use the async keyword in ngOnInit, this means that ngOnInit will return a promise, but that's OK. The framework won't do anything with the returned Promise, it won't await for it's resolution before continuing the application bootstrapping. So you can safely use async.await code on ngOnInit, it's not a problem at all and it's well supported. 👍 Let me know if you have ideas for other stuff I could cover? 😊
I had tried this in a side project. Let me know if im wrong.. but my main concern is memory leaks. If your `simpleSaveOperation` takes 60sec to complete.. and the user gets bored and navigates to another page, it will not cancel.. all requests and this code will continue to run even tho the user is no longer on that page... and any `then()` code from the prior page that executed the promise will also continue to run and unable to be garbage collected.
I completely agree. This example might be okay to prevent canceling since this is basically all one big command. But yeah, I'm a bit worried of people running wild with this and rediscovering the limitations of promises which is the hidden cost of their simplicity.
Notice that HTTP Observables, because they are short lived, don't create memory leaks in general unlike long-lived Observables, because when the HTTP Observable completes all references to the subscribe, error and complete callbacks are released, so anything pointed by those closures is no longer referenced. You can also implement cancellation logic if you want with Promises. Cancellation is an HTTP feature, it's not specific to either Promises or Observables. One way to implement it is with the fetch API. The issue of not cancelling the chain if navigating away would be present either way, but in either case there wouldn't be leaks. What would happen is that the operation would continue unnecessarily. I believe for 99.99% of the cases it's not worth to implement navigate away cancellation logic, but if we need to we can implement eit with both Observables and Promises 👍
I used to think something like that before, but today I think this is mostly a myth. My team has been using Promises since the last year and it has worked very well, we got a lot less code review issues. The async/await syntax is a perfect fit for HTTP, and is widely used in the Node, React, Vue, etc. worlds because it's so intuitive, synchronous-looking and beginner-friendly. There are no real downside of Promises compared to Observables when it comes to HTTP, and due to the async/await syntax they are way easier to use. If you take you most complex Observable-based RxJs code that you can find, and refactor it into async/await, you will be pleasantly surprised at how simple it becomes all of a sudden. Things like conditional logic that is tricky to implement in an Observable chain become super easy when using asyc/await code. 😊
@AngularUniversity it kind of depends how you define a 'leak'. If a promise/observable is finite but you nevertheless don't care about the result, I'd still consider it 'leaky' on some level (albeit a temporary leak) With regards to cancelation logic, you totally can implement this with promises/fetch, but the code will end up looking far more nasty than the clean example here. At that point it's probably best to use observables.
@AngularUniversity Thanks! Do you mean a tuple to an array? Can the second concatMap not destructure a tuple? Sorry for going off topic, but I'm just trying to figure out what I'm missing with rxjs. BTW, loved your rxjs / ngrx courses on Udemy - you have given me rxjs brain damage too 😂@@AngularUniversity
Thank you 😊 Notice that the first method doesn't have cancellation either, if you navigate away the whole chain will continue to execute. If you want to implement cancellation logic, you can do it in both Promises or Observables. Cancellation can be implemented with the fetch API using an AbortController, it's quite simple, or by using an HTTP library that supports it. 👍
Anyway both are not the best solutions in my opinion because is better to call one single api which wraps the three server side save operations to handle the transactions and perform a rollback if one of the three saves fails.
Yes correct, it's just an example of a long observable chain that I could come up with; In practice, there are situations where we need to these type of things tough; like when making an API call to Stripe to trigger a payment, then save something on our database. etc. More commonly, sometimes we don't have control of the backend server, it's someone else's server so we need to end up chaining API calls this way to implement some use case. 👍
In as much as the promise looks shorter and readable, one can also create a readable observable stream too. The biggest disadvantage with promises is that are not cancellable or complex to cancel so when you destroy your component they keep connected to a backend endpoint you no longer need. If the call is lengthy you are gonna spam the backend with calls that you no longer need also the browser Javascript memory on the connection to be finished.
I think that is largely a myth. 😊 Notice that just because we use Observables doesn't mean that we have navigate-away cancellation working out of the box. Even if I would switch the first example from concatMap to switchMap, you would not have cancellation when navigating away. If you would navigate away, the whole chain would continue to execute in the backgound. HTTP cancellation is not especially hard to implement either via the Fetch API or via a library. Notice that most Observable-based HTTP code does not have built-in cancelation either, but i has the downside that is much more complex and less beginner-friendly. 👍
@@AngularUniversity True, good points. I just think with Observables you just use a takeUntilDestroyed at the end of the pipe and it can cancel any request thats happening. Literally 1 line to do it :)
@@innocentmazando3808 Yes that's true 👍, but let's face it the vast majority of HTTP code does not use or need cancelation, wether it's written in Observables or Promises, right? 😊 If you have the need for that more advanced use case, you can always use the right tool for the job, be it RxJs or something else. My main point that I was to trying to bring across is that for most plain, simple, everyday HTTP code, RxJs is likely being overused in a lot of situations. It's like using a cannon to kill a mosquito. 😊 Everyone outside of the Angular world uses async/await for HTTP and it works just fine. The framework gives us alternatives that might work better for you or your team, depending on what you are trying to do.👍
Nice video series. The code is clean and less coding, But.... 1) Using RxJs I could use tap for console log or saving required data to a property without any change in coding, Is There any way for me to use something like tap here?. 2) Async, Await, Try, Catch, Promise... Doesn't makes it look more of JavaScript than TypeScript?. Are we going to JS?.. In-Case I am wrong Ignore this comment 😆. Thank You.
Thank you I'm glad you are enjoying it 😉 For logging you can just use a simple frontend logging library, you don't need anything special for logging. The async/await and try/catch syntaxes are fully supported in Typescript, and there is nothing wrong in using them, it's just another language feature. 😉👍
Although RxJs handles certain edge cases elegantly, like the proverbial search box example, there is almost always a simpler alternative available based on promise-based libraries. Like TanStack query, tRPC, Axios, etc. Not to mention that retry is hardly ever needed in practice at all. Retry is often used as an excuse to justify the unnecessary use of RxJs in my view. 👍
switchMap here would have the same behavior as concatMap. What I was trying to say with the video is that independently of which specific operators we choose from, it's always much simpler to do HTTP using async / await promises. 👍
@@AngularUniversity I disagree. Half the complexity here is shuffling everything back to the 'top level' which isn't needed. Just have the subsequent subs reference the emitted values as a closure and its much, much cleaner. Its also a bit stilted. Sure, if you just have a few dependent values it looks great, but if you have some you want done in parallel, other as dependent, etc, you're looking having to settle them and manage that manually. Now what about things like cancelling things in flight? Throttling? These are not comparable solutions imo.
I think the problem here is more related to the design of the UX than to the usage of RxJS to make the http calls. If you think about it, the user has to create a course and all it's lessons before making the save request. That's pretty complex and unnecessary, you could make separate calls to the backend, one for the course, then one for each lesson as the user inputs the necessary data, etc... I believe recommending to beginners to use Promises to simplify this situation is not really attending the problem, and also it will make them believe that promises will solve the HTTP calls logic. But what if the customer ask for a simple requirement that implies adding cancellation, or debounce time, etc.. then all the code created for the promises will have to be replaced by RxJS, or will very likely turn into spaghetti code. The promises code is not extensible and is prone to become cluttered and hard to maintain. If I were a beginner I would be very happy to know about this, even if I don't have the knowledge yet, at least I now that what I'm doing is not extensible, and if requirements are added, may have to refactor to a more declarative approach
It's the same old justification for unnecessary complexity: what if we need cancellation or debounce? Those are 0.1% use cases or less, most of the times we won't need them. We should focus on making the typical use cases easy and the hard cases possible. async/await can be used for those typical cases, a library or widget can be use used for the rare cases. RxJs is not needed, we should get used to a future where we use it much less, if at all.
@@AngularUniversityI didn't say that you have to use the RxJS strategy, I'm saying that beginners should know that using promises in this scenario will work, but as soon as this code requires new features, will become hard to maintain, since it's not extensible. Code is a living thing that will eventually change in most cases. Also I don't agree that RxJS is not going to be needed at all: currently for Angular, having a more declarative code requires RxJs or a really really complex code with signals using effects (still in preview mode). And things are turning to declarative more and more, basically for its extensibility and maintainability. Learning with simple use cases is nice, but for real world applications with customer requirements that change over time, in my experience, is better to invest time in extensibility, than adding patches and creating a monster
@@AngularUniversityAlso I want to thank you for this video series. It's really great to focus on things that can be improved and I find it very good for the community to have discussions about different approaches and opinions to problem solving
@@codeSurvivor it's a myth promises work fine, everyone uses them outside of Angular. we are actually going the other way, the Angular team is saying that Rxjs will be optional. See here the Signals RFC: " we would like to see the World where RxJS is adopted by teams as a choice for specific use-cases rather than as a mandated or default "best practice"" github.com/angular/angular/discussions/49684
It seems to me that the nesting issue could have been resolved by this pattern: obs1.pipe( concatMap(res1 => obs2(res1)), concatMap(res2 => obs3(res2)), concatMap(res3 => obs4(res3)), // ... ).subcribe()
That looks better, but the main point that I was trying to make is that the same thing can be done much more easily with async / await. It's not that the RxJs version doesn't work, it's that it's unnecessarily complex and not beginner-friendly. 👍
I think if RXJS code is complicated, the problem isn't RXJS. It's the developer. Poor RXJS code can be cleaned and made readable. I advise against using async-await and fully understanding how to use RXJS. It's very powerful and clean.
Don't blame it on the developers, the developers of other frameworks are right on this one. RxJs is unnecessarily complex for doing HTTP, that's the main point of the video. It's like using a canon to kill a mosquito. 😊
While I agree that the observables are less beginner-friendly, I'll argue with the fact that using promises is a better alternative, especially on large applications. A stream is much easier to read if done properly and provides more control of the flow without the hassle. Unfortunately, both solutions presented here are bad and misleading to a beginner. My advice for those new to the Angular world, use observables for async operations and signals for sync operations (you can use observables for the latter too if you want), put in the effort to properly learn RxJS and reactive programming in general. You can use Rx outside Angular and in many languages other than JavaScript (ex: Java, Python, Go, Dart, Swift etc.). But first and foremost, do your own research, and analyse the pros and cons of using observables over promises and the other way around.
It's mostly a myth. Everyone outside the Angular world uses promises for most of the things that we use Observables, and it works just fine. It's just overkill most of the time, that's the main point I am trying to convey in the video.
This scenario was meant if you are calling a backend you can't control, like a third-party. Otherwise, if you can control the backend then it would be better to do one call and make a transaction in the backend; But that was not the main point of the video. what I was trying to communicate is that there are other alternatives in Angular for doing HTTP that are simpler, and encourage to try other patterns that can work better for you, rather than defaulting to using RxJs for everything.
Everything is too complicated when you don't know how to use it. A good developer shoul know both methods and choose when to use. In my opinion observables are more scalable then async/await.
But did you ever try async / await? We've been using it to develop some of the most complex Angular screens that my team has ever put together, and it works like a charm 😊
That is a powerful myth that I hope to help debunk with this video. It's just not true. The latest Angular official tutorial for beginners show async/await, and the Angular team will make RxJs optional and encourage people to try other patterns to see if they are a better fit for your application. 👍
Correct that is just an example, let's assume that you don't have control over the endpoint. For example, you are using a third-party platform like Stripe. 👍The main point of the video is that using RxJs for everyday HTTP tasks is like hunting kittens with a tank. 😊
From my own experience I had an example where using native document.add/removeEventListener was much better (performance wise) solution than @HostListener or fromEvent from rxjs
This example illustrates poor engineering practices. Ideally, you should streamline the process by making only a single API call and allowing the server to efficiently handle the request.
Imagine you don't control the server, like it's a Firestore database, or a chain of calls to a Stripe API. But the main point of the video is that for doing every day HTTP code, there are easier ways.
Here is the playlist for the whole Angular Mistakes Series, enjoy 😉😊 ua-cam.com/video/3oq-gnDzz9k/v-deo.html Also, check out my courses at the Angular University, with content from Beginner to Advanced - angular-university.io
I feel like I was aware of this but needed someone to say it out loud, so thanks.
Thank you, I'm happy to hear that 😊. Yes, I feel the same, it's something that we need to get used to in the Angular world I feel. I've been developing more and more with Promises, they are super well supported in Angular, I'm very happy with the resulting code. 😊👍
When RxJs should be replaced by signals for sync stuff, it shouldn't be by promises for async problems because it adds so many tools out of the box.
So yeah, in some cases, using promises might look "simplier", but by using RxJs you can keep everything declarative. Meaning it will be way simpler to add "bricks" to your observable, than it will be with classic promises. On top of that, you can share those observables way more easily by breaking your pipe into multiple intermediate observables.
Also, if you compare both solutions, the RxJs one isn't really that more complex. The only extra thing to handle is the intermediate pipe to map into a tuple. for the next observable. Does this extra "complexity" will justify to chose promises instead of Observables ? I don't think so.
The concatMap operator is what's translate the best your promise solution. But in many cases that's not the most performant one, mergeMap or switchMap are most of the case more suited and can do thing you can't do easily with promise (meaning it's out of the box, you don't have to add extra lines of code to cancel a request for example).
About cancelation again : with a takeUntilDestroyed you can be sure that every heavy request are being canceled when you destroy your component. Thing that you can't do with promises without adding extra lines of code.
You also have the power of the async pipe with Observable. Which makes things way easier to implement, because you don't need to use ngOnInit anymore, when you have to with promises.
Small detail as well, in your RxJs example you are rethrowing the error when you don't in your promise one.
So to conclude : yes in your example using promises looks easier / simpler. But by doing that, you decide to limit your options in the future. I would say simpler request takes less lines of code with promises, but the more your use becomes more complex, then RxJs will clearly improve the whole thing with well define pipes with very powerfull operators making the code easier to maintain in the long run. And it's reactive, which is a nice touch as well.
It's just an illusion, in general you gain nothing by using Observables for doing simple HTTP, and it's a lot less beginner-friendly. It drives away a lot of people from Angular. Other frameworks all use async / await for years, the added complexity is totally unnecessary in general. I know it's tough to accept, I've written myself code like that for years. 👍
@@AngularUniversity as I wrote in my first comment, it's way more powerful when you are doing more than simple cases.
You want to retry ? You have a simple operator for that.
You want to cache the data, same.
You want to cancel things, idem.
A denounce time ?
Etc.
Obviously you can do the same thing with promises. But you'll require more boilerplate for that. Plus observables are like Lego pieces that you can combine and reuse. Good luck to have the same thing with a promise approach.
You are talking about other frameworks, but what about svelte where RxJs is also pushed by the team ?
What about React and Vue that built their own abstraction on top of axios to handle cases like retry, caching, etc ?
So let's agree that we disagree :D I'll keep writing 2/3 extra lines for small http requests. Because in the end, I'll write less on the entire code base.
@AngularUniversity, I apologize, but it seems there might be a misunderstanding in your example. The example provided appears to offer an inaccurate comparison. It's crucial to recognize that Observables are naturally cancelable, retryable, and cacheable, adhering to established community standards. It's also worth noting that using Observables in this example could optimize the code by avoiding unnecessary API calls when calling the save operation multiple times, poor internet connection, etc. It's somewhat ironic that your example suggests the opposite.
@@RodrigoSalesSilva There is no misunderstanding. Actually the example is not cancellable, but that's not the point. The point I was trying to make is that for 99.9% of HTTP code, all those Observable properties are not relevant. It's like trying to kill a mosquito with a canon. All other frameworks besides Angular HTTP using async /await, it works fine. The creator of Angular itself used async /await in it's new Qwik framework, the latest Angular official video tutorials show async / await. Observables are overkill for most if not all HTTP code, that is the main point of the video, I hope this helps clear things up. 👍
What if the result of the request is used in multiple components and services? How do you push these changes?
Statemanagement with observables makes that easy.
I am sending this to my tl tomorrow 😛. These videos might turn out to be one of the best angular Playlists on UA-cam. Please keep continuing these.
Thank you, it's awesome to hear that 😊 Let me know if you have questions or concerns about Angular, I might just make a video with it, I'm always looking for new ideas. 😉
@@AngularUniversityI do have a doubt. Sometimes in projects I have to use ActivatedRoute to fetch params from the URL and then I need to call api requests the same way you did in the video.
I cannot use firstvaluefrom(promise) in this case because my params are dynamic and paramMap is a never ending observable.
So, how can I avoid Rxjs chaining in this scenario?
As a newbie, I really appreciate the mistakes series. Very helpful.
I'm happy to hear that, let me know what type of mistake would you like me to cover, or the biggest pain point that you find in Angular? 😊
I think the initial problem you presented is just poor RXJS code. Ideally it should be something like this:
// Function to make sequential requests
getAllData(): Observable {
return this.getLessons().pipe(
switchMap((lessons) => this.getCourses(lessons)),
switchMap((courses) => this.getUsers(courses)),
catchError((error) => {
console.error('Error in sequential requests:', error);
return throwError(error);
})
);
}
Using switchMap in this case doesn't change anything. This is still unnecessarily complex compared to using async/await, that's the main point I was trying to bring across. 👍
@@AngularUniversity where is the complexity?
@@dev-grilado there's no complexity here, no more than using async/await.
This is so clean and readable
Thank you, it's so simple, isn't it? 😊
I'm starting to like this mistake series. Can't wait to see more.
Stay tuned, two new videos already recorded 😉
This makes so much sense. One question: if you are using NgRx for state management, would you then convert the final promise to an observable to process it in NgRx?
That is a great question, that is actually one of the places where I still use long chains of Observables at least for now, to write Ngrx Effects which I think is your use case too, right? In those cases, I tend nowadays to call an async/await service method, get back the promise and convert it to an Observable, if the logic that I'm trying to express is a good fit for Promises. I only use RxJs if I really have to, and it's been a breeze of fresh air for both me and my team, I feel we can get a lot more done. 😊 👍
For data fetching especially into a reactive store with effects etc, IMHO you should use observables all the way down to the angular http client, as that would allow things like switchmap etc to cancel the http requests. One disadvantage of using promises is you lose this cancellability and end up with zombie promises, wasteful work, wasteful network activity and possibly even race conditions depending on how your async code is structured.
I agree with the thesis of this video but feel there are caveats and gotchas. Don't just blindly start converting a bunch of requests (especially simple queries) without taking stock of what you're losing in the process.
Yes Yes Yes Finally!! This is should be normalized among the community and everyone.
The fact is that HTTP requests are async and can be used as promises is an underrated concept which is lost among the RxJs wave of tutorials.
It is much simpler and clean though no one is aware of it.
I remember one time I told someone about it and he was not believing that this is a true thing at all !!
Hats off to @anularUniversity
I believe we need more videos on this
Thank you, its awesome to hear that. 😊The crazy thing is, it's always been there from the beginning, a lots of projects use it. It's just not been mentioned a lot, but the feature is there if we need it, and it's a great alternative to RxJs for doing the most typical everyday async operations like HTTP 😊
Great example! This is how Angular should be done going forward. The first approach is ugly and should be avoided as much as possible!
Keep up the good work with these series!
Thank you so much, I'm glad you are enjoying the videos. 😊 Yes I agree, if you want to save yourself and your team a world or unnecessary pain, consider switching to Promises when doing HTTP, it's a super natural fit. 👍😉
I'm starting to develop a new, large project. I am struggling with some architectural decisions... I am using almost all the new Angular features in this project, but the only feature I am not using at the moment is the new Signal API. I can't find a complete solution with Signals... I have always preferred to use promises for API requests (like in this video) and reserve Observables for intercepting requests (for authentication and loading, for example), emitting global states like session or notifications, and facilitating communication between unrelated components.
I would love to get rid of zone.js in the near future for this project, but I don't exactly know how to architect my current app to align with that objective.
Thank you for your videos.
Your approach sounds exactly like what I do nowadays, use async / await for HTTP and Observables for application-wide communication. 👍 Signals are still evolving, I think that the latest Signal API is already a good way to replace BehaviorSubject on shared services, so less RxJs is needed. 👍 When Signals are plugged into change detection, we will have a better idea how things will evolve in the future. If you want to make your application compatible with Zoneless in the future, might as well put all the data already inside signals. Btu I think there will be new signal primitive introduced to handle objects and automatically create a signal for each property recursively. There is ngRx Signal Store already for that, but I imagine there will be something similar at the level of the framework as it's such a fundamental primitive for signals. Iwouldn't put a top priority in getting rid of zones, they work very well and simplify development a lot, I really like them I think the developer experience is very good, i rarely run into any issue 😊 I can't predict the future, but there is a good chance that zones will still be very popular even after signals are here, unless the new way of doing signal-based components is super easy as well. Cheers and thank you for commenting 👍😊
@@AngularUniversity
Hi Vasco.
I have watched a lot of your university content - many thanks for the excellent content.
You say we should use signals to go zoneless; can we not go zoneless using observables with async pipes?
I also think toSignal is an inherently bad idea because you have to initialise it with a false value. What are your thoughts on this? I had a problem where I was initially calculating (in an effect) a default value for a form field when it was null. toSignal caused problems because the first argument it passed to the effect was the false value, meaning an incorrect default was calculated for the form field. I think toSignal can fool you into thinking you can turn an asynchronous source into a synchronous one without repercussions. As it stands I am never using toSignal again, which takes away a lot of the motivation for signals.
Declarative rxjs + Angular is honestly absolutely beautiful and my favorite type of programming. It is painful for me to see the Angular team going in the opposite direction. I wish everybody could see how good it is and invest the time into learning it.
I think for http requests promises make more sense and appear cleaner in code. Do you have any recommendations for using promises in an OnInit? While it can be marked as async I think it will not wait for the results prior to the page load, so the behavior is a little unexpected and maybe undesirable?
It's amazing that you ask that, because I just finished recording minutes ago Mistake #4, where I cover just that. 😊 It's OK to use the async keyword in ngOnInit, this means that ngOnInit will return a promise, but that's OK. The framework won't do anything with the returned Promise, it won't await for it's resolution before continuing the application bootstrapping. So you can safely use async.await code on ngOnInit, it's not a problem at all and it's well supported. 👍 Let me know if you have ideas for other stuff I could cover? 😊
@@AngularUniversity Awesome, thanks for the info!
@@megarustog You're welcome, enjoy the channel! 😊
That's gonna be a great playlist 😁
Yes, it's already available on the channel, episodes 1 and 2 😉Here is the playlist - ua-cam.com/video/3oq-gnDzz9k/v-deo.html
I had tried this in a side project. Let me know if im wrong.. but my main concern is memory leaks. If your `simpleSaveOperation` takes 60sec to complete.. and the user gets bored and navigates to another page, it will not cancel.. all requests and this code will continue to run even tho the user is no longer on that page... and any `then()` code from the prior page that executed the promise will also continue to run and unable to be garbage collected.
and don't get me wrong... the reason i tried this in a side project was because i hate using observables for http.
I completely agree. This example might be okay to prevent canceling since this is basically all one big command. But yeah, I'm a bit worried of people running wild with this and rediscovering the limitations of promises which is the hidden cost of their simplicity.
Notice that HTTP Observables, because they are short lived, don't create memory leaks in general unlike long-lived Observables, because when the HTTP Observable completes all references to the subscribe, error and complete callbacks are released, so anything pointed by those closures is no longer referenced. You can also implement cancellation logic if you want with Promises. Cancellation is an HTTP feature, it's not specific to either Promises or Observables. One way to implement it is with the fetch API. The issue of not cancelling the chain if navigating away would be present either way, but in either case there wouldn't be leaks. What would happen is that the operation would continue unnecessarily. I believe for 99.99% of the cases it's not worth to implement navigate away cancellation logic, but if we need to we can implement eit with both Observables and Promises 👍
I used to think something like that before, but today I think this is mostly a myth. My team has been using Promises since the last year and it has worked very well, we got a lot less code review issues. The async/await syntax is a perfect fit for HTTP, and is widely used in the Node, React, Vue, etc. worlds because it's so intuitive, synchronous-looking and beginner-friendly. There are no real downside of Promises compared to Observables when it comes to HTTP, and due to the async/await syntax they are way easier to use. If you take you most complex Observable-based RxJs code that you can find, and refactor it into async/await, you will be pleasantly surprised at how simple it becomes all of a sudden. Things like conditional logic that is tricky to implement in an Observable chain become super easy when using asyc/await code. 😊
@AngularUniversity it kind of depends how you define a 'leak'. If a promise/observable is finite but you nevertheless don't care about the result, I'd still consider it 'leaky' on some level (albeit a temporary leak)
With regards to cancelation logic, you totally can implement this with promises/fetch, but the code will end up looking far more nasty than the clean example here. At that point it's probably best to use observables.
Thanks for the video. I'm confused by why the map is necessary in the rxjs example. It seems to map to exactly the same thing
It maps a tuple to an object, or you can use the alternative notation that I showed as well.
@AngularUniversity Thanks! Do you mean a tuple to an array? Can the second concatMap not destructure a tuple? Sorry for going off topic, but I'm just trying to figure out what I'm missing with rxjs. BTW, loved your rxjs / ngrx courses on Udemy - you have given me rxjs brain damage too 😂@@AngularUniversity
Very nice example here ! Thanks Vasco 😎
Thank you Alain, I remember you from Twitter. 😉 welcome to the channel. 😊👍
Another great video! Just one question if you don't mind? Does the second method allow cancelling of an inflight request?
Thank you 😊 Notice that the first method doesn't have cancellation either, if you navigate away the whole chain will continue to execute. If you want to implement cancellation logic, you can do it in both Promises or Observables. Cancellation can be implemented with the fetch API using an AbortController, it's quite simple, or by using an HTTP library that supports it. 👍
@@AngularUniversityOh ok yes of course. Thanks for the help!
@@awesomewidgets4298 Your're welcome, enjoy the channel. 😊
It is really informative and helpful 🙂 Thanks....
Most welcome 😊
Anyway both are not the best solutions in my opinion because is better to call one single api which wraps the three server side save operations to handle the transactions and perform a rollback if one of the three saves fails.
Yes correct, it's just an example of a long observable chain that I could come up with; In practice, there are situations where we need to these type of things tough; like when making an API call to Stripe to trigger a payment, then save something on our database. etc. More commonly, sometimes we don't have control of the backend server, it's someone else's server so we need to end up chaining API calls this way to implement some use case. 👍
Great content! Thanks.
Glad it helped!😊
It is really informative and helpful playlist. Thanks....
Thank you, I'm glad you are enjoying it 😊
Your courses are the best. Thank you
Thank you Gilberto, I'm happy to hear you enjoyed them. 👍
RXJS Brain Damage - haha!
love it
Yes! 🤯🤯🤯 🤣🤣🤣
Thanks!!!!👍👍👍👍
You're welcome. 👍
In as much as the promise looks shorter and readable, one can also create a readable observable stream too.
The biggest disadvantage with promises is that are not cancellable or complex to cancel so when you destroy your component they keep connected to a backend endpoint you no longer need. If the call is lengthy you are gonna spam the backend with calls that you no longer need also the browser Javascript memory on the connection to be finished.
I think that is largely a myth. 😊 Notice that just because we use Observables doesn't mean that we have navigate-away cancellation working out of the box. Even if I would switch the first example from concatMap to switchMap, you would not have cancellation when navigating away. If you would navigate away, the whole chain would continue to execute in the backgound. HTTP cancellation is not especially hard to implement either via the Fetch API or via a library. Notice that most Observable-based HTTP code does not have built-in cancelation either, but i has the downside that is much more complex and less beginner-friendly. 👍
@@AngularUniversity True, good points. I just think with Observables you just use a takeUntilDestroyed at the end of the pipe and it can cancel any request thats happening. Literally 1 line to do it :)
@@innocentmazando3808 Yes that's true 👍, but let's face it the vast majority of HTTP code does not use or need cancelation, wether it's written in Observables or Promises, right? 😊 If you have the need for that more advanced use case, you can always use the right tool for the job, be it RxJs or something else. My main point that I was to trying to bring across is that for most plain, simple, everyday HTTP code, RxJs is likely being overused in a lot of situations. It's like using a cannon to kill a mosquito. 😊 Everyone outside of the Angular world uses async/await for HTTP and it works just fine. The framework gives us alternatives that might work better for you or your team, depending on what you are trying to do.👍
Nice video series.
The code is clean and less coding, But....
1) Using RxJs I could use tap for console log or saving required data to a property without any change in coding, Is There any way for me to use something like tap here?.
2) Async, Await, Try, Catch, Promise... Doesn't makes it look more of JavaScript than TypeScript?. Are we going to JS?..
In-Case I am wrong Ignore this comment 😆.
Thank You.
Thank you I'm glad you are enjoying it 😉 For logging you can just use a simple frontend logging library, you don't need anything special for logging. The async/await and try/catch syntaxes are fully supported in Typescript, and there is nothing wrong in using them, it's just another language feature. 😉👍
Thanks 👍@@AngularUniversity
In which situation rxjs approach would be better? Is there any? When retry logic would be required?
Although RxJs handles certain edge cases elegantly, like the proverbial search box example, there is almost always a simpler alternative available based on promise-based libraries. Like TanStack query, tRPC, Axios, etc. Not to mention that retry is hardly ever needed in practice at all. Retry is often used as an excuse to justify the unnecessary use of RxJs in my view. 👍
Good job
Thank you 😊
“If you look at it and think, what’s wrong with it, then you probably have developed rxjs brain damage” 😭😭😭😭😭😭😭😭😭😭
Yes! 🤣🤣🤣
The original chain feels funny. Why do all the concatMap flattening instead of just switchMap and clousures?
switchMap here would have the same behavior as concatMap. What I was trying to say with the video is that independently of which specific operators we choose from, it's always much simpler to do HTTP using async / await promises. 👍
@@AngularUniversity I disagree. Half the complexity here is shuffling everything back to the 'top level' which isn't needed. Just have the subsequent subs reference the emitted values as a closure and its much, much cleaner.
Its also a bit stilted. Sure, if you just have a few dependent values it looks great, but if you have some you want done in parallel, other as dependent, etc, you're looking having to settle them and manage that manually. Now what about things like cancelling things in flight? Throttling?
These are not comparable solutions imo.
Great
Thank you, enjoy the videos! 😊
I think the problem here is more related to the design of the UX than to the usage of RxJS to make the http calls. If you think about it, the user has to create a course and all it's lessons before making the save request. That's pretty complex and unnecessary, you could make separate calls to the backend, one for the course, then one for each lesson as the user inputs the necessary data, etc... I believe recommending to beginners to use Promises to simplify this situation is not really attending the problem, and also it will make them believe that promises will solve the HTTP calls logic. But what if the customer ask for a simple requirement that implies adding cancellation, or debounce time, etc.. then all the code created for the promises will have to be replaced by RxJS, or will very likely turn into spaghetti code. The promises code is not extensible and is prone to become cluttered and hard to maintain. If I were a beginner I would be very happy to know about this, even if I don't have the knowledge yet, at least I now that what I'm doing is not extensible, and if requirements are added, may have to refactor to a more declarative approach
It's the same old justification for unnecessary complexity: what if we need cancellation or debounce? Those are 0.1% use cases or less, most of the times we won't need them. We should focus on making the typical use cases easy and the hard cases possible. async/await can be used for those typical cases, a library or widget can be use used for the rare cases. RxJs is not needed, we should get used to a future where we use it much less, if at all.
@@AngularUniversityI didn't say that you have to use the RxJS strategy, I'm saying that beginners should know that using promises in this scenario will work, but as soon as this code requires new features, will become hard to maintain, since it's not extensible. Code is a living thing that will eventually change in most cases.
Also I don't agree that RxJS is not going to be needed at all: currently for Angular, having a more declarative code requires RxJs or a really really complex code with signals using effects (still in preview mode). And things are turning to declarative more and more, basically for its extensibility and maintainability.
Learning with simple use cases is nice, but for real world applications with customer requirements that change over time, in my experience, is better to invest time in extensibility, than adding patches and creating a monster
@@AngularUniversityAlso I want to thank you for this video series. It's really great to focus on things that can be improved and I find it very good for the community to have discussions about different approaches and opinions to problem solving
@@codeSurvivor it's a myth promises work fine, everyone uses them outside of Angular. we are actually going the other way, the Angular team is saying that Rxjs will be optional. See here the Signals RFC: " we would like to see the World where RxJS is adopted by teams as a choice for specific use-cases rather than as a mandated or default "best practice"" github.com/angular/angular/discussions/49684
@@codeSurvivor Thank you, yes I think the opinion based content, while subjective is where most of the value is, I will try to make more of it. 👍
It seems to me that the nesting issue could have been resolved by this pattern:
obs1.pipe(
concatMap(res1 => obs2(res1)),
concatMap(res2 => obs3(res2)),
concatMap(res3 => obs4(res3)),
// ...
).subcribe()
That looks better, but the main point that I was trying to make is that the same thing can be done much more easily with async / await. It's not that the RxJs version doesn't work, it's that it's unnecessarily complex and not beginner-friendly. 👍
"RxJs brain damage" haha. Definitely got a little of that after years of using Angular. I am Italian Chef of creating rxjs spaghetti code.
Same for me, it gets second nature after a while 😊
I think if RXJS code is complicated, the problem isn't RXJS. It's the developer. Poor RXJS code can be cleaned and made readable. I advise against using async-await and fully understanding how to use RXJS. It's very powerful and clean.
Don't blame it on the developers, the developers of other frameworks are right on this one. RxJs is unnecessarily complex for doing HTTP, that's the main point of the video. It's like using a canon to kill a mosquito. 😊
While I agree that the observables are less beginner-friendly, I'll argue with the fact that using promises is a better alternative, especially on large applications. A stream is much easier to read if done properly and provides more control of the flow without the hassle. Unfortunately, both solutions presented here are bad and misleading to a beginner. My advice for those new to the Angular world, use observables for async operations and signals for sync operations (you can use observables for the latter too if you want), put in the effort to properly learn RxJS and reactive programming in general. You can use Rx outside Angular and in many languages other than JavaScript (ex: Java, Python, Go, Dart, Swift etc.). But first and foremost, do your own research, and analyse the pros and cons of using observables over promises and the other way around.
It's mostly a myth. Everyone outside the Angular world uses promises for most of the things that we use Observables, and it works just fine. It's just overkill most of the time, that's the main point I am trying to convey in the video.
I would suggest you remove the background music. I think it takes away from the quality of the video and lesson.
What would you do if the 3rd request fails? Wouldn't data be out of sync?
This scenario was meant if you are calling a backend you can't control, like a third-party. Otherwise, if you can control the backend then it would be better to do one call and make a transaction in the backend; But that was not the main point of the video. what I was trying to communicate is that there are other alternatives in Angular for doing HTTP that are simpler, and encourage to try other patterns that can work better for you, rather than defaulting to using RxJs for everything.
@@AngularUniversity ok thanks, that's what I thought 👍
@@ulgmail You're welcome 👍😊
I write every operation within its own function, then it is more understandble.
Yes, but that's not my main point. We can make it look nicer, but it's still unnecessarily complicated when compared to using Promises.
Everything is too complicated when you don't know how to use it. A good developer shoul know both methods and choose when to use. In my opinion observables are more scalable then async/await.
But did you ever try async / await? We've been using it to develop some of the most complex Angular screens that my team has ever put together, and it works like a charm 😊
I thought RXJs is more powerful and should be used over promises and async await
That is a powerful myth that I hope to help debunk with this video. It's just not true. The latest Angular official tutorial for beginners show async/await, and the Angular team will make RxJs optional and encourage people to try other patterns to see if they are a better fit for your application. 👍
The real problem here is the endpoint, but understand that is only an example
Correct that is just an example, let's assume that you don't have control over the endpoint. For example, you are using a third-party platform like Stripe. 👍The main point of the video is that using RxJs for everyday HTTP tasks is like hunting kittens with a tank. 😊
From my own experience I had an example where using native document.add/removeEventListener was much better (performance wise) solution than @HostListener or fromEvent from rxjs
This example illustrates poor engineering practices. Ideally, you should streamline the process by making only a single API call and allowing the server to efficiently handle the request.
Imagine you don't control the server, like it's a Firestore database, or a chain of calls to a Stripe API. But the main point of the video is that for doing every day HTTP code, there are easier ways.