Lucas Paganini (00:00.961)
Hey, welcome to Adventures in Angular, the podcast where we keep you updated on all things Angular related. This show is produced by two companies, Top End Devs and Unvoid. Top End Devs is where we create Top End Devs to get top end pay and recognition while working on interesting problems and making meaningful community contributions. And Unvoid, which offers remote design and web development services with specialization in Angular for companies that truly care about quality.
we'll talk about Angular signals versus RxJS. With us are GD and expert panelist Armen Vardanyan.
Armen (00:45.041)
nice to be back for another episode
Lucas Paganini (00:47.881)
and our also Angular expert Subrata Mishra.
Subrat (00:52.604)
Hello everyone
Lucas Paganini (00:55.165)
I am Lucas Paganini, I'm the CEO of Unvoid and you're hosting the podcast. So let's get started. So Armin, you wanted to start this discussion. Do you think there's a particular way in which you think it would be more productive for us to start? Do you think we should just talk about the benefits of signals or just skip that and just go directly to how to...
Do interop with them or what do you think would be best?
Armen (01:29.149)
So I guess if we are talking about signals versus observables or RxJS in general, we first need to understand a couple of things. So let's talk about what signals are and what observables are. Of course, we kind of know everyone who has touched the subject has an idea of what is going on. But a deeper understanding of it is that we're not always using, for example, RxJS.
correctly and I'm saying correctly for the lack of a better word. It's not like we're using in a wrong way but rather than it is not used in the primary way that it is intended. So for observables which we are more familiar with we talk about streams. So a stream is kind of like events. Okay so a good example of a stream is like when we create an observable using the fromEvent function
and for example say let's listen to all the click events on the document, right? So this is a stream. And that stream you can get some notifications like oh, click happened there, click happened somewhere else. What is important about an observable, and this is true about any observable, is that it doesn't have any state. It's not for managing state really. It's just.
a thing that keeps you not finding about stuff. But you don't get to keep that stuff in the sense that like you cannot ask the observer like, oh, what was the last click or like what was the click before that, right? We cannot do that. And even if we treat it as a state as happens a lot, like for example, if we make a search query, right?
And we use some operators like the bounce time whatever to make an HTTP call switch map blah typical scenario Even in this case We're treating it like a state. Oh, you know, there is a search term, right? the user entered something and they're waiting for a result, but Our just don't know about it if we create it as a simple observable It will just you know emit an event, but you need to kind of
Armen (03:49.513)
to it or use a side effect or whatever other scenario so that you can have this state kept somewhere for future reuse. Like this is a very popular and bad case bad practice scenario where people will write a method and then inside it they subscribe to something to get the value or they subscribed in
ngOnNit for example and kept the value in some property on a class to reuse somewhere else because async pipe doesn't solve that problem we can put an RxJS value in the async pipe in a template no need to subscribe unsubscribe async pipe will do that but if we need that data somewhere else in the component in the TypeScript file in the class of the component then we kind of need to do some work around
or we need to use a behavior subject. So behavior subject is something that is closer to a signal or the way over engineers to be considered like an equal to a signal. But behavior subject, it does store the last value that we have. There's also replace subject where we can store several values and so on. So behavior subject is kind of what we're looking for in that case, but it's still is
complex to be treated as just a simple primitive solution to the problem that one signals on the other hand they are not events so people really need to stop treating them like observables but simpler that's not the case they're not observables one main difference from the top of my head they're always synchronous
Observables can be synchronous, like if you create an observable of a simple array, it will be synchronous. It will execute the supply to it, the functions will execute immediately. And that's completely fine. That's what we would expect. But signals can also be, sorry, observables can also be asynchronous, like the click observable. Also, observables have a concept of being complete. So.
Armen (06:07.513)
At some point, maybe you have unsubscribed or from something or you created an observable from a promise and when a promise results Observable is done Also observables have internal errors. So if somewhere down the pipe You get an error then the observable is killed But it could probably not have not fulfilled whatever purpose For which we have created it, right? Signals on the other hand are way simpler in that scenario
Signals are actually values that we can read at any time. We need to call it like a function and we'll get the value, whatever is inside it. We can change its value using its methods and we can create new signals from it. That's where the interesting part comes in. So the part where we create new signals is where we get to enjoy this reactivity. If you create a computed signal,
then it will update every time the signals it uses update. Like if I create two signals, A, B, and then do a sum computed return A plus B, anytime A or B changes, this sum signal will also change. And the real reactivity stuff we get to see in the template where we can just call the signals and anytime they're updated this part of the
view will be re-rendered. Well, right now it's not exactly like that. When we get signal-based components, it will be more fine-grained reactivity and change detection. But, you know, you get the idea. So, signals were kind of born as a response to people who didn't like having too much RAGS in Angular, because there were lots of reactive tasks that were not related to any asynchronous stuff.
but you still need to handle it using RxJS. For example, if you take lots of existing state management solutions, NGRX, right? Uses observables, because it makes sense. You don't just want to store the data, you want also to notify everyone, every component that data has changed. But in this case, the data change isn't really an event in the sense that RxJS events are. It's not a clique, it's not something that just
Armen (08:33.297)
happened is the state that got changed and we do not really care how it changed. So we don't need to treat it like an event. We can just treat it as a signal, right? That something has changed and we need to do something. On the surface, it looks like the same, but the difference, when we understand this difference, it helps us better understand when to use which, because right now lots of people are going around, or should we just dump
only use signals and the answer to that is no, no. You can't get rid of RxJS in all scenarios. There are things inside Angular that will forever be tied to RxJS like HTTP client. There is zero sense in making a HTTP client call to be a signal because signals are synchronous and you are dealing with an asynchronous HTTP call.
It doesn't have a value initially. So what happens if you read the signal before the promise is resolved? That is a business logic question. It depends on your implementation. Library cannot give you an answer to this. So it makes more sense to have an observable there. Okay. HTTP client returns an observable. If you want to make it a signal anyway, okay, go on. There is an interoperability package. You can do that. But the library itself, the client itself will not.
use signals for that because it won't make any sense, right? So yeah, this is kind of the platform on which all the discussion is going on about this topic.
Lucas Paganini (10:02.799)
How would?
Subrat (10:08.102)
Yeah. I was.
Lucas Paganini (10:10.993)
I was having a recent conversation with some coworkers and I was trying to give them a mental model of when to use signals versus RxJS. So the way that I went about it and it clicked for them, so maybe that might help some other developers that might be listening to this is, I basically said that everything
that you can do with Angular signals, you can do with RxJS. Doesn't mean that it was made to be used that way, but you can. Like everything that you do with Angular signals, you can do with RxJS. And there are things that you simply cannot do with Angular signals, such as dealing with a lot of asynchronous activities. So, for example, if you want to do...
a debounce before you make a request and you want to declaratively say that you're going to retry this request up to three times, then you should still stick to RxJS because it was made for that. But if you have a particular value that depends on another value, and so you want the reactive benefits, you want the reactivity,
dealing with a particular aspect that is asynchronous, then Angular signals would be the best choice there. Doesn't mean that you can't use RxJS, but it would make your code simpler if you simply used Angular signals. So that was my way of trying to explain it to them.
Armen (12:01.085)
That's of course a good observation. Signals are very, quotation marks, poor compared to observables. Of course not in the sense of quality but rather functionality. You can't even filter values of the signals. If you do a computed signal you need to return something from it. So the thing about it is I have these rules of thumb.
Subrat (12:13.483)
Yeah.
Armen (12:29.617)
Like when should you ditch, in what scenarios should you take away RGS for the signal. If you have a rule of thumb number one, if you have a behavior subject, like 100% you can replace it with a signal. You didn't use that behavior subject for some natural event that occurs in your UI. Then it would be just a simple observable. You created a behavior subject because you needed the value. Just drop a signal in instead, everything will work the same.
unless you are doing some crazy async stuff, which again, 99% of scenarios, people don't do that with behavior subject. They do it with observables, like from an event, from an async thing. Usually, most probable scenario is you are using behavior subject for some logic that happens somewhere and you just need the value stored. So go on, replace it with a signal. So next rule of thumb, if you see something like
whatever observable that subscribe and this property equals the value from observable, something like that. Just drop it, just use a signal, use sets on the signal and if you are deriving whatever from that observable use computed, if you're using the type operator, replace it with an effect. Also please consider maybe you don't need that side effect. Usually you don't need to use effects a lot, like it's not good.
to use effect a lot, like it really, really needs to be a side effect, like writing something to local storage, yeah, that makes sense as a side effect, but in most cases, you don't really need that. And finally, if you have something that is related to several components that is coming from somewhere else, then you probably need RxGIS there. You don't need a signal there, especially if you're trying to put it in a service.
So here's an interesting thing, and I really wanted to talk about it. So, on Twitter, it became more popular to use the method of connection between signals and observables a third way, other than using to signal or to observable. So there are these functions in the RGS interop package where you can convert an observable to signal. And it makes perfect sense. It's a very good function.
Subrat (14:45.813)
Mm-hmm.
Subrat (14:49.158)
Yeah.
Armen (14:56.153)
What it does, it will take an observable, it will take an initial value because an observable can be like async and not have a value yet. So you need to provide like initial value, whatever. Okay, and it will convert it to a signal. And it makes perfect sense. It will also unsubscribe automatically from that observable, right? You create a signal from whatever you used it in template component that destroyed. So this signal and.
Subrat (15:15.354)
Mm-hmm.
Armen (15:21.745)
Subsequently each subscription to that observable are destroyed. So it's really cool. The problem with it Comes when you try to re-export stuff from services using this method Imagine you have an observable in a service like something from a socket or whatever And you think yeah, whatever I can export it as a signal, right? I don't need Well, I think I don't need the observable in the
right? So if you have, for example, a web socket created from RxJS and you exported the data from it as a signal and this is the only way the components access it, right? Now it means that if your component got destroyed the substitution will still be there, like the observable will continue to live because it's from a signal, the source of this observable, the context was the service. The service is not destroyed, only the component is destroyed.
Subrat (16:15.895)
Hmm.
Armen (16:22.065)
So now you have no way of like closing the socket because you don't have the observable. The observable got stuck in the service. You only have the signal. And signals, again, as I said, they have no, they don't even not have a mechanism for completion. They don't even have the idea of being complete. Like signal is a volume. What do you mean the signal is complete? There is no such thing. So either you use RxJS directly in the sense that
Subrat (16:37.517)
Yep.
Armen (16:50.981)
whatever, you use RHS in services, and then in the components you can do to signal and then unsubscribe when you ditch it. Which is perfectly okay, I mean, between these two approaches, there is like zero quality difference, you can use both approaches, whichever your team prefers. I even personally don't have a preference, like it will depend on what I try to implement. Or there is this cool function called connect, and it's not really a function in Angular, it's a function that people write.
They call it connect because it makes sense. And what it does is it will take an observable, it will take a signal and will connect them. So anytime you use the signal, this observable will trigger these changes. So it's sort of like to signal, but you get to keep the observable like separate from it. It will be an effect in the other context. So in your component, you will call connect, right?
Subrat (17:38.446)
Hmm.
Armen (17:49.237)
and it will connect your signals to the outer world. And now on the destruction of your component, this context will be destroyed and this subscription will be destroyed, right? And that is a really interesting way of doing things. Like if you have your own state management solution, which lots of projects do. Like imagine if you have a project that has been using subject in a service for, I don't know, a decade.
there's zero sense for you to go to NGRX or whatever, your project's already huge. But it makes sense to use signals instead of that. So you can just drop the connect method somewhere in your code base, maybe even in the services that you are using to manage state and just connect it and use signals in your component. And you have now zero problems with having your subscriptions destroyed or whatever.
So there's lots of caveats, right? This is the biggest one we have still discovered. In general, I would say a rule of thumb for me, I'm not saying this is a super best practice, but for me to be careful, anything that is shared between components is observable for me. Because it continues to live on and it depends on other stuff which can be async also. Anything that lives in the component.
that is not async by nature. Like, yeah, if I'm doing a from event or whatever, that will be an observable for me. But anything else, a local state, everything should be single. That's a rule of thumb for me. It's not a best practice. You may find other situation where you might think, or whatever, in this case, I think is better to use an observable or vice versa. But if you follow this rule of thumb, it will save you lots of headaches.
If you think you need to get more experience until you try more crazy stuff, just in my opinion follow this rule of thumb, you'll be fine in most cases.
Subrat (19:49.886)
Yeah, I have also like similar rule of terms like I think you both as you both have already explained. So mostly I recently made a video on this thing like to signal and to observable. So in that what I observed is like while develop doing the video one thing is for a starter project means if someone is starting up they mostly
like mess up with unsubscribing the observable and then slowly the projects goes build a big project then they have memory leaks and all as much as possible and if it is not possible to do with signal then use observable and convert that to signal or vice versa then if you have that mindset then it might be like
in future when your project grows you'll have less memory leaks and all because I think if you go with ideal scenario yeah everyone say you should not unsubscribe and you should always use async pipe and everything but that's not the always happen for all the projects we have projects like with messy switch map messy everything so
Armen (21:13.433)
Um, yeah, but there's also possibilities to introduce network leaks through other combining operators, even with the async pipe. You can do that. So async pipe is not a silver bullet. Signals are in the sense that there is literally zero things you need to do with signals. Yeah. It uses the component context. Component is gone. So is the signal. I mean, signals don't even have.
Subrat (21:18.718)
Yeah
Subrat (21:24.428)
Yeah.
Subrat (21:29.03)
Yeah, because it is bind with the component lifecycle and yeah, signal is gone.
Armen (21:44.173)
One of the beautiful things about CNOS is that it's subscription, again, for the lack of a better word, mechanism, it's like the reverse of observables. So observables, they will sort of hold an array of references to subscribers, right? So unless you unsubscribe, it leaves somewhere someone is referencing and you got yourself a memory leak. So essentially, it is even obvious when you do like...
Subrat (21:56.8)
Mm-hmm.
Armen (22:12.413)
functions that combine latest, you say, oh, this, I'm subscribing to them. Signals are reverse. When you read a signal, you call it like a function. You get the value of it always, but it also does a bunch of other stuff. Like it figures out if it is being called in a callback of a computed function, for example. If it's in its callback, it will itself keep that.
reference to the outer context so it's in reverse. It knows that the other signal needs it. And that is how it keeps... that is why you don't need to unsubscribe from it because it's the reverse. If the computed thing is gone then everyone that it used it will also be gone in that sense.
Subrat (22:47.671)
Mm-hmm.
Subrat (23:05.463)
Hmm.
Armen (23:10.829)
having a ref count on an observable and it's a hot observable unless you have like one subscription and when the other subscription is gone it will die that more or less the same mechanism right
Subrat (23:18.118)
Yeah, I think to just to simplify if I'll just try to refresh it so in observable we like The sub the producer doesn't know like how many people are subscribing it just emit the data but in case of signal the producer knows that okay, these things are subscribed and again lack of better word like Subscribe and when there is some change the producer will change in the Producer I'm saying about the computed or effects so they know
which are signals are they are using and they will computed accordingly. Right. That's what you meant. Yeah.
Armen (23:58.293)
Yeah, more or less like that. It's like the computed function itself does not say, oh, I have this as something I need to keep. It's the other way. They got red, they know where they are red, so they keep it in them. And then this signal, the simple signal that we have declared, it will die with the component and will also take with itself all the subscribers.
Subrat (23:59.476)
Mm-hmm.
Subrat (24:04.012)
Mm-hmm.
Subrat (24:07.639)
Yeah.
Subrat (24:22.273)
Mm-hmm.
Is I think that comes to the point, like if you're declaring a signal in a in a service which is injected in root level. So it will be stay active throughout your application.
Armen (24:40.269)
Yeah, that's what we talked about. That's the same, but for signals, again, it's not a big problem. It's like, yeah, whatever, we have this object that has a value that we can read, it can live on. Anyway, like if we have an observable, it will be the same case. It will live on, but we can say that we have unsubscribe, but in the case of signal, what is there to unsubscribe, right?
Subrat (24:51.87)
Hmm.
Subrat (25:04.717)
Yeah.
Subrat (25:08.982)
But yeah, I think as you as you discussed from the beginning that we can't leave RxJS like in what Lucas also say, if you have debounce time and all, I think those things we are still going to lay use from like a form object at debounce time at retries and everything. And then convert the whole thing to signal by using to signal or connect whichever is preferable than.
Use that value directly. So you don't now it need not need to unsubscribe with them by using tech until operator and all those things.
Armen (25:46.393)
Also, yeah, correct. And also another thing about signals is that they can unwrap values of other signals. Like a promise, right? So promise of a promise of X is just a promise of X, right? That's how we do like dot then dot then chains and so on. And observe was not like that. Like they don't unwrap automatically. That's why we have like.
Subrat (25:52.867)
Mm-hmm.
Subrat (25:58.754)
Hmm.
Armen (26:14.013)
casting operators, like switch map and stuff, because we have observables of observables, higher order observables. And observable of observable X is observable of observable of X. It doesn't get unwrapped when you put the logic. And it makes sense because it's async, so you need to define a strategy, like if you have this many emissions, which one should we take starting from the first emission or the last emission or completion or whatever. There are lots of scenarios.
Subrat (26:21.602)
Hmm.
Armen (26:43.913)
make sense for observables to unwrap. But signals, they do unwrap. And when we convert an observable to signal, it also will unwrap. So a very good example of this is imagine you have a signal for a search query, right? And it is bound to some input, so user input, so the signal gets updated. What I want is when the user enters new data based on this query
signal, I want to make an HTTP call and I don't know, this is the result. It's a very popular scenario. So what people and I even I personally at first I thought yeah well this is the case for using an effect, right? I should write effect, when the signal changes, blah blah, set another signal I don't know in whatever way. But see, you don't need to do that. You can write a computed signal which will
Subrat (27:17.448)
Mm-hmm.
Armen (27:42.361)
Make an HTTP call and pass the query signal to it, right? Then you do to signal on this result, which is observable using HTTP client. And I just returned that value. You just say to signal this. And this will be a signal of that other value. For example, I don't know, we're waiting for an array. We can put the initial value as an array. And...
Subrat (27:52.395)
Yeah.
Armen (28:11.573)
Angular would unwrap it in a template and where we call it. It will unwrap it, so we will just get the value. So just with one line of code you have done a pretty kind of hard complex scenario. If you want to go further, you can use an observable with debounce time and so on, blah blah, and so you now have two observables, but they work with each other for a signal.
Subrat (28:30.439)
Mm-hmm.
Armen (28:41.737)
Again, it will be just two lines of code. You don't have to read it. This is the whole reactivity thing and it's really awesome Compared to any other solution to this case like you literally Declaratively describe what each thing is You don't describe any behavior and you don't Issue like any commands on those signals whatever
Subrat (29:07.811)
Yep, I think...
Lucas Paganini (29:12.949)
I have one question regarding the connect function versus the to signal. I immediately thought of a very naive way of coding this connect function. And I wonder if there would be any issue with it. Like, why can't we, for example, just store the observable in a variable? And then in the next line, you call...
to signal and then you store the signal. Then you have references to the observable and to the signal. Would that be a valid approach to kind of a connect function? Or is there anything that is done inside the to signal function that actually mutates the observable and makes my initial reference unusable for some reason?
Armen (30:07.178)
I think if we come from the rxgs side, I mean if you do it with the signal first approach you will write an effect you would also put allow signal rights true Maybe it will be kind of complicated, but if we come from an observable we can just say you know I don't know source.pipe take until destroyed and You know tap signal
Subrat (30:15.924)
Mm-hmm.
Armen (30:33.317)
dot set whatever value and that would be it. So we don't even need to write an unsubscription because we already put take until destroy. So it's gonna be like two lines of code. Any other approach, you don't need the ref, the connect function already gets the reference to an observable, it takes an observable and see that connects them. We already have the reference to the observable. You don't.
need any other way of accessing it. It's still there, you can just call it and say answer square for example and the signal will just live on with the final completed value of the observable, better for seeds. That's the whole idea of it. It's like, it's probably very similar to how to signal for example is implemented although it has a bunch of other checks and stuff like initial value and blah but you don't need it because you already have a live
It's not a computed signal derived from an observable. It's a signal that you have just connected. You can just call set on that signal if you like in some sense. Or, or if you are very pedantic about people don't need to be able to mutate this signal, because in the end of these kind of computed from an observable, then you can just write a computed and export that computed signal.
The thing is you just don't lose the observable. The observable is there. It's not re-exported. And you can connect, disconnect using your component. In the constructor called connect, that's it. To unsubscribe then automatically you will not have problems.
Lucas Paganini (32:11.833)
Gotcha. I have another related question, not exactly about the conversion, but about how is everyone handling the pending state? Like between the moment where the component loads and you're waiting for the data to come in to actually show it, you need to somehow be aware that you're in this loading or...
pending state and show that in the UI somehow. There are different ways to do that. I, in the past, implemented something called weight groups, which it was a very simple counter. And then if the count was bigger than zero, then it was loading something. And if it was zero, then it finished loading. And then I created decorators to use that in methods that this method can only run.
Armen (32:43.805)
I'm sorry.
Armen (33:00.253)
Thanks for watching!
Lucas Paganini (33:05.957)
when this weight group is ready so that it would be easier to block methods while it's in a pending state. But I know that every developer handles that in a different way. Some developers simply create a property called loading and set that to true or false. So, yeah, how do you do that?
Armen (33:24.827)
Oh.
Armen (33:28.049)
So interesting you would say that because isn't every solution essentially creating a property called loading, but in a different place? So there are different approaches to this. In NGRX, what I used to do is I have data, then I have an object called loading that has all the same properties as the entire state, but showing if it's loading or not. And also error that also shows this error, that error. And
with latest NGRX things like create feature and stuff, it will just create a big selector that you can select anything from there. That's perfectly okay. Now there is also select signal in NGRX, you can select the state of the signal and just do whatever with it. If we're talking plain Angular, no state management, when we say loading, we mean there is an async thing going on, so there is an observable. So why not if you create an observable, like an HTTP client call,
HTTP.get, whatever. Then when you make it to signal, you can put initial state, I mean, you need to put initial value. The initial value can be, I don't know, status loading or something. You can make all the HTTP calls to be like this wrapped values like load status, loading status, I don't know, pending status, error status, success, and so on.
And just treat every HTTP request like that.
Armen (35:00.969)
The templates might be, I don't know, not very great because you would do like this value dot loading and so on and such. But you know, it's again, it's even I would say matter of taste. I don't like this wrapped thing. So I use... I would select the whole slice from NGRX because I'm using NGRX. I would say, I don't know, view model dot loading dot whatever.
ng-if else show this. Well, in the future we will write just if, whatever. So yeah, I guess with 2C null will kind of force your hand. You will need to come up with a solution to that because it will say, okay, it's an observable and what's the initial value? What the user is going to see if you just call it in a template, for example.
So this is actually good because it will result in more homogenous code base in this scenario because lots of people just, okay, I want to convert this to signal. When I convert to a signal, okay, I will put some loading, Boolean or whatever there. And that will become the sort of de facto standard of what people do in such scenarios. Again, only if you're using plain Angular with state management libraries. Who knows? Whatever solution you come up with.
there are different approaches. There are people who kind of sort of implement state machines inside the state management libraries. It's also a valid thing, but it's complex and it's a team with a great understanding of this particular data structure, right? So, highly depends.
Subrat (36:38.482)
Mm-hmm.
I saw use case of this by using interceptor. So they are what they are going on interceptor. They're making creating a like having a reference of all loading possible where they are calling and then assigning that part from the URL to true or false and then same reading that from the from that year.
Subrat (37:07.34)
Yeah.
Armen (37:07.557)
Yeah, but see this scenario also depends on the business logic. Like if you want to always just show some loader when HTTP call is going on, sure, great solution. An interceptor knows if there's a request, it will put something in the state management and say, you know, show this global loader. But if you're just loading some piece of UI and you want to block this piece and there is a spinner going on.
Subrat (37:34.555)
Mm-hmm.
Armen (37:37.129)
not the same so you can do anything with interceptor for that, right? Instead, again, if you wait to show something in what I would do if I were in charge of having the UX in my hands, what I do, I would use resolvers and I will handle anything in the resolver like make the HTTP call, time the result, pass the component, and an interceptor
Sorry, not an interceptor. If the user tries to navigate somewhere, I will just show the loading anyway, because they are doing a navigation. So if I'm using a resolver, in that case, it makes sense because I clicked somewhere, it needs to load this data before showing. So now I'm showing a spinner or whatever on the top of the page. Ah, yeah, okay, now it's loaded. From UX perspective, it makes sense.
It doesn't make sense if we are doing optimistic updates. If we, for example, have the part of the state already loaded, like we're in the list page, and we have some of the items that we need on the details page, so maybe we wanna navigate to the details page and show part of the data and loaders and then all the data, so it's more of a smooth experience and transition for the user. Again.
entirely depends on what you want to check. Maybe you want animation, but you don't want animations. I guess if resolvers are not limited to sending that one value.
Armen (39:13.669)
it would make sense like if we if we could give them an observable of stuff and initially just say a loading then in a component where we just need to create an input because now inputs can be bound to resolve data right and just get the data if it's loading show whatever we need to show in this component if it's not then we're cool just show the data but it's a real
Subrat (39:33.314)
Mm-hmm.
Armen (39:42.193)
can overcome in a specific official way. We need to see what we really need to show in the UI and just implement that.
Subrat (39:47.186)
yeah but we are going with signal then that we need to handle for each for each thing
Subrat (39:59.437)
Yeah.
Armen (40:01.241)
Yeah, but we can do all the stuff in an observable and make it to signal.
The entire part of our HGIS is at our fingertips. We can just then convert it to signal and use it without the async pipe and whatever.
Subrat (40:10.571)
Mm-hmm.
Subrat (40:15.79)
Cool.
Lucas Paganini (40:21.889)
Gotcha. I don't know if I have any other specific questions regarding RxJS versus Signals, but I do wonder if that's just because I've read so many articles about that nothing pops to my mind. Maybe they're just somebody listening and thinking, ask that question, ask that question, but it's just nothing coming up.
Armen (40:44.889)
I think we will have plenty of time covering all the things because again, the scenario I mentioned today that we talked mostly about the connect function and what problem it's for. I think it's the first kind of issue we discovered that, oh, you know, in this case we might run into something like this. So here's the solution. There will be more. Trust me. Right now, actually the best advice, don't use signals on production code bases. So yeah.
Subrat (40:55.794)
Yeah.
Subrat (41:06.05)
Production news.
Armen (41:16.157)
I can imagine when signals go into production and really heavy enterprise applications implement really crazy requirements, people are going to find more issues. When people start, we mentioned the WebSocket example, people start working with that, there will be issues. There will be lots and lots of articles and saying, oh, how do you do this? How do you do that? Right now I have like a million ideas of what bad cases may arise from this.
And we need to be prepared to that. So today we discussed several of them. Main takeaway, I think should be there is no fight between our EGIS signals. You need to make them interoperate. That's why we have all these functions and approaches. And we also talk about rules of farms. So maybe in general, if we follow those rules, 95% of issues will go away.
and then we will be left with 5% real issues.
Lucas Paganini (42:20.397)
Yeah, but there's also all the limitations of it. Like, for example, the fact that... Okay, maybe that's not a specific limitation, but it's an improvement that hasn't been done yet. I think one of the strongest selling points for signals is the fine-grained change detection, which we don't really have currently. So, I mean...
Armen (42:44.941)
Don't you? I think you do. I think you do have it right now. You can... well there are no signal based components so it's not the most fine grained. But you can just put your components to change detection strategy on push, all of them. And use signals and ditches on JS. You could do that like five versions ago with RxJS.
Subrat (42:47.8)
Yeah.
Lucas Paganini (42:54.265)
Yep.
Lucas Paganini (43:04.61)
Right.
Armen (43:12.549)
You could use async pipes, you can make everything in observable. It wasn't very maintainable. That's why we're doing signals. That's why we have this, oh, okay. You now can use it everywhere. But imagine an application where for every single property you create, it's a behavior subject. Well, you might think, oh, you know, this crazy, it's an overkill, but aren't you going to have that with signals you will create and what's the difference if you, oh, it's more characters to write new behavior subject as compared to signals.
write a helper function, I don't know, uh, bhs or whatever and call it, it will create a paper subject. Like, uh, you get where I'm getting with this. You already have it. You already kind of have this fine-grained reactivity. It's not the exact thing that we're gonna get. The exact thing that we're gonna get is, will be view-based change detection. So,
Lucas Paganini (43:52.857)
Yep.
Subrat (43:54.446)
Mm-hmm.
Subrat (44:00.171)
Yeah.
Lucas Paganini (44:06.769)
Mm-hmm.
Armen (44:08.589)
Every time a view is created for a directive or a nested template Change detection will be on its level. So you know the signal change then it's bound to this template Okay change the tech for this template right now We are changing taking from top to bottom like from the root of the application to the end
Lucas Paganini (44:26.913)
Yeah, and I'm not saying that this is a bad thing for signals. I'm just saying that one of the reasons we could use as developers to justify the usage of signals hasn't landed yet, because we can already do that without signals. Like, as you were saying, we can just use behavior subjects. So one of the strongest selling points, which is going to be this fine-grained reactivity, like even finer-grained,
Armen (44:47.963)
It's...
Lucas Paganini (44:56.993)
you're correct, we can already have a very fine-grained change detection by using on push.
Armen (45:03.065)
I would say zoneless change detection.
Lucas Paganini (45:05.529)
That's better. Yep.
Armen (45:08.145)
For me, it makes perfect sense, like why we don't have it yet. Signals themselves are a small library inside of Angular. We have all these functions that are specific to signals. You know you can use signals outside of components. You can just create a project, install Angular Core, import signals from there, and use them. So we got all this new stuff, which potentially have a bunch of bugs and problems and issues.
and emergent approaches. So it's already a big thing. We now need to first have like six months where people play with it, toy with it, find issues, until we can say, okay, signals themselves as a thing are stable. Now for another six months, they will go into production, people will find more issues and blah, blah. In that meantime, people will get the fine-grained reactivity and you will say, okay, you now have signal inputs, you have...
I don't know, a zone with apps and signal based components. Okay, now try this out. We already know signals themselves are okay. Now let's try the change detection change because this upgrade for the change detection, it's a huge thing. It's not something that team will do overnight. Could they withhold it and maybe release everything together in the next week? Sure, but now you got to deal with problems from signals. You got to deal with problems from our HGS interop
On top of that, you're gonna deal with lots of bugs in the change detection mechanism. The last time we had any connection to change detection stuff was with the introduction of Ivy. And you can't imagine how many different short-lived plugins were there that would say, okay, pass this injector, change detector somewhere, somewhere for something to work. You will have this scenario when fine-grained reactivity lands. It's just too much.
Now you can say, okay, signals are production ready. Feel free to rewrite signals in your component and use them with zone.js because it's perfectly okay. Then, okay, you wanna get rid of zone.js. Now you had like six months, even for migration, this is better, you had six months, seven months to convert everything to signals. If you did that, now, okay, just make your component signal true, signal-based components.
Armen (47:33.757)
And when you are done with that, whenever you are done with that, because signal-based components are gonna still interrupt with usual components. When you are done with all that, okay, go on ditch Zone.js, put ng-zone-no-op, and you're done. You have completely fine-grained reactivity all across your application. So it's easier to do it iteratively too. So I guess for me it makes perfect sense why we get the...
The initial document that we received for me, it was, oh, this is huge, like signal-based components, signal inputs, signal outputs, and so on and so on. Like function-based lifecycle hooks, after render, after next render. We already have that in Angular V16.3, I guess. We already have that, actually. But, you know, and then when I learned that we only will get signals, computed signals,
and not the old bunch of other stuff. I was initially disappointed like, oh, I would love to play with signal based components and so on. But eventually I felt like, yeah, I kind of understand right now there's a bunch of issues going on with signals. It's not sustainable to try to deal with all of these issues right now. Who knows, maybe the team works out something better in the process of, you know, doing this whole stuff.
Subrat (48:53.65)
Yeah. I think also like if you give a lot of things, people will try to implement everything and they will mess up with it and the gate repo issue will fail with a lot of issues and the team is, yeah.
Armen (49:12.477)
You can't imagine how many different scenarios people will come up that as a maintainer, as an expert, as a senior developer, you could never have thought of people doing that. But now they did that and they've discovered some issues. Who are you to go to tell them, oh, you're not supposed to do that? Well, they do that. Now there's a whole issue going on with it. Especially if it's in a library somewhere. Oh, okay. That's going to screw a lot more stuff.
Subrat (49:17.227)
Mm-hmm.
Subrat (49:24.462)
Hehehe
Armen (49:40.493)
lots of people are using that said library and now you've got your sort of problem. Somehow you need to fix that. So, yeah.
Subrat (49:44.726)
I think all things make sense. I think the community is taking a nice decision, at least for Angular. Because if you see the popularity of Angular slowly, rapidly decreasing, not slowly, it's decreasing. Now I think somehow if it helps and companies started integrating Angular, it will better be a good pathway for Angular.
Lucas Paganini (50:19.033)
Definitely. And as Armin said, this is just the first topic we're bringing up. So we're probably going to have more episodes to talk about Signals and RxJS. But yeah, I think for this one, this is more than enough for all of you getting started on this subject. So let's do some quick promos. So Subret, do you have anything in particular you would like to promote?
Subrat (50:39.082)
Yeah, I would like to promote the similar to the which we have discussed. I just released a video on this Monday. So it might be, you know, when you're listening, it's already maybe one or two weeks back, but go ahead and watch that one. Like it's on stick. This was in my channel and you have like how to use both signal and observable together in application and with scenarios. And I also had like.
a previous video where I discussed how all the chain detection will work with view kind of rendering with on pose without on pose with JoanJS and everything so have a look on those videos
Lucas Paganini (51:29.157)
Nice. How about you, Armin?
Armen (51:33.937)
Not something particularly specific, but recently I've taken to Twitter and started posting small stuff about NGRx, mainly. So if you're interested in NGRx or you're learning it, give me a follow. I usually post stuff that is also in my articles. You can also ping me if you have questions. NGRx is my favorite part of the Angular ecosystem. So yeah, if you're interested in it.
give me a follow, you can also check out my AndroidX articles on Dev2. I plan on writing more in the future, but I don't have enough time right now.
Subrat (52:10.026)
Yeah, when GRS is great, man.
Lucas Paganini (52:16.749)
Yeah.
Lucas Paganini (52:21.093)
All right, my promo is just gonna be the usual. So I'm gonna promote my company on void.com. If you are looking for anyone to help you with an Angular application code, or you want to fully delegate that, or you know somebody that is looking for people to help with an Angular-based application, or maybe just training and things like that.
Then be sure to contact us on envoi.com and we'll see what we can do to help you. So I think this is all. Thank you Subret and Armin. Oh sorry Subret, you were going to say something.
Subrat (52:53.55)
Oh.
Subrat (52:57.706)
Now I was saying this is a pretty good episode for having a mindset of why to use signal, why to use RxJS.
Lucas Paganini (53:14.521)
Definitely, that makes in comparison to reading the entire RFCs, I think this is much more friendlier. But yeah, I still recommend everyone to read the RFCs because they are going to go way deeper than what we went here. But yeah, I think this is a good way to start the audience on the subject.
Subrat (53:15.148)
Yeah.
Subrat (53:31.358)
Yeah, maybe someone is driving and listening to what they can't read, but they can listen. So it's a good thing.
Subrat (53:44.194)
See you, bye bye.
Lucas Paganini (53:45.458)
True. All right, thanks everyone, and I'll see you in the next one.
Armen (53:52.381)
Thanks everyone, bye.