За тази лекция
In this talk, the speaker shares insights on JavaScript signals and proxies, emphasizing their roles in developing reactive applications. He explains that proxies act as wrappers around objects, allowing developers to intercept operations like assignment and property access, while also highlighting their performance limitations. Conversely, he describes signals as fine-grained dependency tracking primitives that efficiently manage application state and improve UI updates by notifying only dependent nodes of changes. The speaker discusses practical examples of both technologies, illustrating their unique capabilities and potential use cases. He also mentions the ongoing development of signals within the JavaScript community, proposing their integration as a standard feature in web browsers.
Пълен транскрипт
Challenge accepted. [music] Challenge Challenge accepted. Challenge [music] accepted. Challenge accepted. P2 is always [music] challenge accepted. And now let's keep the JavaScript energy rolling. The next speaker His debut the beauty is a speaker right here at def challenge accepted and he nailed it. That's why we invited him back. He's an IT team lead at an working on realtime sports data platforms which means if you're checking football
or volleyball results while pretending to work, thank him. >> But IO isn't just about code at his company still building. He actually won the prize for best javelin thrower. So yes, he can both roll data pipelines and literal spears. >> He has also been on national televisions talking about docs which honestly makes him the most versatile speaker with head sports software snouters. >> Today he's diving into
signals and and proxies in JavaScript and knowing yuku expected reactivity not just in code but on stage two >> from Sophia Bulgaria. Please welcome back to death challenge accepted Ilcepted. Challenge accepted. Challenge accepted. Okay, I think we're good now. Uh, thank you very much for the introduction. Also, great presentation by Kasi. It ties in actually really well with what I'm uh going to talk about today. Uh,
and yeah, as the guy said, this is my second time presenting here. Last year was my first. So, before I start, I actually have a question. who was here last year. Okay, so if you Yeah, if you listen to my talk last year, you probably remember or I will remind you that I had some chocolates with me on stage that I threw at people that answered my
questions. Don't worry, I don't have chocolates this year, but I do have some t-shirts that I want to give out to people that answer some of my questions during my talk. So if you're interested, feel free to raise your hand and I will try to spot you so you can answer my questions. Okay. So what I'm going to talk about today is JavaScript signals and of course
proxies because we need [snorts] to have a comparison between the two. And as it says in the title, it's for me at least a good starting point to unite JavaScript developers because as I think we can all agree, we are a bit of a dysfunctional group of people in the JavaScript community. Basically, everyone has their own opinion and technology that they prefer to use, but there is
no one single truth, let's say, in JavaScript. So, a little bit about myself. My name is Yuku. Uh I am an IT team lead at Init. As the guy said, uh my team specializes in gathering realtime sports data and then providing it to to clients. That's basically it. Not going to go to go into too much detail. Uh and yeah, I would like to take this opportunity
also to apologize uh to you because I literally got married last night. So I'm coming from my wedding. >> thank you very much. And also I would like you to applaud again because my wife is in the audience. So I'd like a huge round of applause of her for as well. Okay, now back to the boring stuff. So what is a proxy? Let's try to understand first
what a proxy is. Basically, a proxy is like a wrapper an that wraps around an object which gives you the power to intercept any operations that you might want to do with an object like assignment, accessing, deletion, etc. So, it gives you a lot of power if you want to do some uh customizable things and functions. And how do these proxies work? So, as I said, it's
a wrapper that wraps around the original object. Uh, and the good thing is that the interface that uh and syntax that it uses, it's basically the same as uh a plain JavaScript object. And if you're using a proxy, as I said, all operations that you would like to do on your object need to go through uh the defined handlers in the proxy. And of course, if you
haven't defined any specific handler, it will fall back to the default state of the And here are some of the more common handler traps like for example get which intercepts property access, set for example, which also intersects property assignment, uh delete property, which intercepts property deletion, and others. But these are more of the common ones that are being used. And of course as with everything there are
some limitations and proxies have them too. One of the I think biggest limitations is the performance overhead. As you can imagine you have uh an object and you have to define multiple custom functions that need to be executed each time you need you want to do something with that object. So you can imagine that you add functions, you add functions, you add functions and on each iteration
these functions have to be executed in order to get your result. So there is the possibility with uh a huge object, a huge data set to get some performance overhead. It's not going to break your app, but if it's but if your app is performance critical, it could be an issue for you. And here is a quick example where we have an iteration of like 1 million
times. We have a plane object. We also have a proxy object and both have a property of count which we what we only do is just increase the count uh the count value. But with the proxy as you see in the handler we have to go through the set uh handler trap which doesn't do anything special even as you take a look at it. But still we
need to go through that additional layer of functionality before we get the result that we want with the proxy. So this is my first question for a t-shirt. How much slower do you think the proxies are compared to direct access? Who would like to try and guess? Okay, I saw someone in the back. Close. Does anyone want to try or you can try again if you want?
I will give you it's it's more Perfect. They are 10 to 100 times slower than direct access. And I don't know if you want to come up here. I can give you your t-shirt. Do you want a white or a black one? Here you go. So, yeah, they could be 10 to 100. Yeah, good job. It's not that scary. You see, I've made the questions quite easy.
I want to give out these t-shirts. I don't want to wear them at home anymore. So, yeah, I clean them. I clean them. Don't worry. So, yeah. And why is that? Why are they so much slower even in this uh very simple example? Because as we said, we need to invoke these handler traps every time. And you can imagine that over a million times, it could get
quite a bit of uh work that needs to be done. Some other limitations are deep reactivity. With proxies, you can only intercept top level property access. If you want to intercept nested levels, you need to do some recursive functionalities in order to get that uh functionality. And also you cannot proxy primitives. Uh as we said, a proxy is a wrapper basically an object that wraps around another
object. So you can only of course proxy object, arrays and functions because as we know arrays and functions at the root level are still objects in JavaScript. So you can proxy an array or a function. And some real use cases for proxies. For example, Vue still uses proxies for their reactivity system, but they are planning to change that using vapor mode hopefully soon and signals by the
way. Okay, so now that we understand a bit proxies, let's talk about signals, which unlike proxies in uh that intercept object operations, signals are basically a fine grain dependency tracking primitives, you can think of it, you can think of a signal as a special kind of variable that tells everyone who uses it whenever its value changes. And let's see how they work. For example, they have automatic
dependency tracking. Here in our example, we can see we have a state of first name, last name, and middle name, and also a computed state for the full name. And basically what autotracking dependency does is that a computed signal automatically discovers any other signal states that it's dependent on. For example, full name is dependent on first name and last name and it only gets invalidated whenever one
of the values for either in this case first name or last name changes. So my question here is what would happen? What do you think would happen if we change the value of middle name knowing what uh auto dependency tracking is and what full name consists of? What do you think would happen? Who said nothing? You. Okay, I'll give I don't have any more >> Okay. Yeah.
Nothing. Nothing. You can come and collect your t-shirt from the taxmen. >> [laughter] >> Uh so yeah uh we can actually I've prepared a demo for this let me just show you the demo so we can see it in action. So you trust me but I could be lying to you. You never know. So we need to check of course. So, let me just refresh. They told
me I have a t-shirt for you. It's the gods of challenge accepted. Okay. So if we change let's say the first name to Jonathan we can see that the the function was ex was executed which is the first console log and then the triggered computed signal is the console log that we had in our uh computed state. So we can see that the computed signal was triggered
because we changed one of its dependencies. Let's try it with last name as well. Let's Are there anyone offs in the crowd? Okay, cool. You're Jonathan Evanov now. Okay, we can see that the same thing happens again because last name is also used in full name which is a dependency. But and let me clear this so there is no confusion. If we change your name, your middle
name to Bon Bon, we can see that yeah, we triggered the the click function in order to see that yeah, we did change the name to Bon Bon. But as you can see, the computed signal was not triggered because middle name as the guy that took something from the tax man said was not a part was not a dependency in full name. And also if we click
to clear the names again we trigger it because first and last name are dependencies in the computed signal. Moving on. The second thing is lazy evaluation. And lazy evaluation uh indicates that basically computations are not eagerly evaluated when they're declared nor when they are uh nor are they immediately evaluated when their dependencies change. Basically they are only evaluated when you specifically request their value. And as you
can see again we have a count signal a double computed state which doubles the count and an increase count function which increases the count of course and specifically requests the value of the double computed signal. So again for another t-shirt what do you think would happen when we load the application knowing lazy evaluation in our example? Who said nothing? You. Yeah. I mean hopefully you are correct.
Again we'll need to check and see but I know the guy that wrote the code I think you are going to be correct. Okay let's quickly try to show the example. Okay this is our last one. So one two three. Cool. You don't have to give your t-shirt back. But yeah, as we said in our example, we don't request the value of the computed signal in any
part of our application when it loads. We just declare it and change its value when we do something else. But now if I click the increase count, you can see now that the computed uh the console lock in the computed signal is being shown because as you remember in our function we use double.get get and this is specifically requesting the value at this point when we click
increase count and that's why at the beginning of the application when we load it it doesn't happen we don't see the console work another thing about signals is that they have memorization and I'm guessing you probably figured it out but it's basically the same as basic JavaScript computed signal computed signals cache their last value so that if you have some really big calculations, computations or whatever, you
don't uh the computed signal does not get re-evaluated and recomputated. Uh if you want to use the same value, it basically gets it from the cache if it's there and uses it instead. So yeah, in our example again a count a double computed property, a function that accesses the double value and an increment function again that updates the count value and gets the double. So what do
you think would happen again for a t-shirt when we execute the access double function? Uh let me try to rephrase it. Which which uh console logs do you think we will see when we execute the function? let's maybe that was a bit too tricky of a question. I probably didn't phrase it too well, but let's see what happens. So again when we load the application nothing happens
because of lazy evaluation. Now this triggers the increment function. This triggers the double function. If we look at our example this is our increment function. This is our double function. So let's click increment. everything all of the console works appear because as did you say it it will get shown I will take it as a as a correct answer so you can come here and I can
give you your t-shirt uh but yeah since this is the first time we are calculating this value here you go since this is the it's not part of the cache as my colleague said it's not part of the cache so basically we Don't look at that. Uh so yeah, we get and see all of these uh logs because we need to do all the calculations. But now
let me clear this so you don't get confused about my skills. So now if I click access double which does not increment the value but only gets it. We can see that we only get the access value console. We don't do any computations. So we don't increase anything because it's already in the cache and we get it from there. So that's memorization in signals. And last but
not least, signals have very efficient updates. So when a signal changes, the good thing about it that it only notifies its dependence. For example, there is no v do vdom diffing like in view for example. Signals keep an internal dependency graph where the nodes are the states. The edges are the computations and defects and when one node changes only its dependent nodes or connected nodes are notified
and updated. We don't update the whole dependency graph as maybe we will do with vom diing. So if you want efficient and fast updates, it's very good for that as So why signals? Well, the goal of signals is uh basically to provide infrastructure for managing complex application state so that the developers can focus more on the business logic rather than doing some traditional repetitive uh code and
worrying about state. And they basically address uh the challenges of traditional reactivity. By offering granular control updates only where necessary. As we said it the whole dependency graph does not get updated or rerendered. It only rerenders the parts where it needs to. Better performance, less overhead compared to virtual DOM diffing which enables faster UI updates and also less code uh from your framework, simpler debugging. This is
planned to be a part of the JavaScript API which gives uh the opportunity for web browsers to integrate it in their dev tools which could which could make it much easier to debug without having to install some other dependencies exactly for that or specifically for that. And last but not least and actually this is my favorite part and also why I called the topic a way to
unite JavaScript developers because it will be framework agnostic. Basically, it could work like a universal primitive for uh reactivity, reducing the need for specific boiler plate from specific frameworks and improving interoperability. And what is that is basically that you can have a complex application with a lot of microservices that use as crass would probably use React some other microser could use Angular, Vue, whatever. and currently or
if you don't do something custom or there is maybe something that I don't know yet but you need to handle your state based on each framework's uh specific cases but if you use signals you can have one source of state management which can be used throughout all your microservices and throughout all different frameworks and I think this is really cool because you can use the good parts
of each uh that you like and that are your for your specific case from each framework but still have a single source for state management. So yeah, this was proposed by the TC39 committee not a while back and that's why currently it's uh in stage one where basically the proposal is under consideration and they have to devote some time to uh to check it to see if
it's worth it but hopefully it is. Then it needs to go through the second stage where they have chose the preferred solution which might of course change. Stage 2.7 where the proposal is improved in principle. Moving on to stage three where the proposal has been recommended for implementation and no changes should be expected at this point. And lastly the uh last stage four where the feature is
complete and ready to be included in the standard. So as you can see there are some there are quite some steps yet that need to be done but hopefully they will get done fast and in the near future maybe one or two years we could have standardized signals and actually still uh even today uh there are implementations of signals but for specific frameworks for example if you're
interested you can look at views alien signals which I saw u a topic about them at the conference and they were outperforming basically every other framework work even solid gs. So let's try to wrap things up a bit. What are some of the key differences between proxies and signals? And uh we need to understand that this is not a topic that says choose signals over proxies. It's
basically you need to understand what uh you need to do what your job is and choose the best tool for it. And also the good thing is that they can complement each other and work together to build if you need some low-level handling of data and objects. So to recap, JavaScript proxies intercept and customized object operations they are have a they have a they are broad synchronous
and imperative. Crassi already said what imperative means. You give exact instructions in order to get the result that you want. uh it requires custom and recursive logic for the productivity and dependency tracking and it can have performance overhead and signals. They manage reactive reactive state without automatic updates. The API is more simple and declarative. You just express what you want to achieve but not specifically tells how
to achieve it. It also has built-in automatic dependency tracking and memorization and it's optimized for minimal and precise So when to choose which? As I said, the choice is strictly up to you and your your use case. But to give some examples uh for proxies, if you really need a low-level interception of objects and you really need to do some custom uh validation, logging, let's say some
other things, but at a really low level, then yeah, you would need to choose proxies for this. And also if you want to build a reactive system where the entire object graph needs to be observed and the performance is not critical and for signals as we said if you want fine gray interactivity optimized highly optimized precise updates to the UI if your application is performance critical uh
if you want uh uh foundation and one place for your state management you You can even build a state management library with it. And again last but not least and actually my favorite that it's cross framework. Uh it can leverage the potential of a native browser for and become a primitive for reactivity basically. So yeah uh this was it. Thank you for answering my uh questions and
yeah listening to my talk. And if you want you can check out the demo code. I still need to push some things. Don't worry about it. Working in production and yeah, if you want to connect with me, feel free to connect with me. These are my social media. So, thank you. >> Thank you. [applause] Thank you, IL. Do we have any questions? [applause] There is a question
there. >> Uh, do we have Yeah. >> There there is the question. >> Five, four, three. >> Don't worry. >> Hello. Thank you for the presentation. Firstly, I just wanted to ask uh your opinion on uh the usage of signals in uh microrend applications. >> In what applications? >> Micro front end. >> Yeah, I think it would be really helpful because you can have the signals become
your one source of state management for activity and you can use it throughout your micro front end. So I think that would be really cool and a really good use case for it. So yeah, I think it would be highly cool and good to use it like that. >> Is there another question? >> Careful t-shirt. >> No, you don't. >> Don't worry about the time. There are
no lightning talk speakers. >> I didn't know I can do that. I would have th No, I have PTSD from last year. >> Please one question for the >> Who who wants to get thrown at the face with a t-shirt? is the question. >> Is the question that is the question >> where Jesus Christ so you can meet meet Ilo in the speakers corner during the next
break. And now let's send him off the stage with big round of applause. Ilco V.