Check out a free preview of the full Enterprise Architecture Patterns course
The "Preserving State & Merging Streams" Lesson is part of the full, Enterprise Architecture Patterns course featured in this preview video. Here's what you'd learn in this lesson:
Lukas discusses how to preserve state within a stream. The scan method behaves like the reduce method by continually updating an initial value. The scan method can also receive a partially applied function for cases when multiple streams are being merged.
Transcript from the "Preserving State & Merging Streams" Lesson
[00:00:00]
>> I think it's pertinent. Then if we're going to talk about observable streams. The question is how do we preserve state in a stream? And so one of the things that I ran into is that in my code on this basic sequence, I'm clicking and well it was doing something I probably broke it.
[00:00:26]
See if I did or not, I know why my shift key is not down, is that if I click, how do I keep track of how many times I've clicked it? Well, that requires state, how do I handle that in a stream? And so what we have here is a pretty simple example is we have a button and a ball.
[00:00:55]
And all we're doing is we're tracking the x, y properties of a position object. So, we have a button, we have a ball, from here let's stop take a breath and let's work the system what is the initial output? Well It's right here so what we're doing here is we are looking for the right button, and then we are capturing that in our final input.
[00:01:43]
Is we're taking this position object, whatever this is, and we're assigning it to the local property that we're binding to. So what is happening in between? Well, a couple things, the first thing that we're doing is we're taking the event, which is the mouse event, and we're just returning 10.
[00:02:07]
And then from there, we're saying we're going to start the stream with an object of x&y and so it's going to be x100 y150. And so, up to this point, nothing fancy and if I go over here maintaining state. We just have a ball that's at 100, one 50.
[00:02:28]
Now what we're doing here is we're using the scan operator, which is very much like the reduce function on an array and that it takes. The current or accumulated value, so think of this as state, for the stream, it takes the current value that's being passed in. And then it's allowing you to perform some operation and whatever you return that goes into.
[00:03:01]
It gets saved as the accumulated value, It gets passed in on the next time around. So what we're doing here is we're saying when we click this take start with 10o and 150, but take that current position have X and Y and we just want to add current which is 10 to the existing X property.
[00:03:33]
So we're just saying, take this number which in this case is 10 and add it to X and return a new object. And so, from here, what this allows us to do is, wait for it, everybody sit down it'll be okay. Wow Cool, right and if we go into just so we can see this.
[00:04:08]
We had 10 but if I change it to 100, that's what that current value is. So that's what's being passed into the stream. So, if I go back to the browser now, you can see that instead of passing 10, we're passing 100 which creates a much larger increment.
[00:04:29]
All right, now this segues right into our next question. What happens if we have more than one stream?How does that work? Well, if anybody's ever been to a McDonald's, or any other, typically any other fast food restaurant, and you get a soda, or a pop, or soda pop, depending on what part of the country or the world you're in, and you go and you put your cup under the fountain and you're getting soda well, what you're really getting is a stream of carbonated water and syrup that then comes together and produces soda.
[00:05:19]
And so this is how we can handle more than one stream by simply merging them together. So I think of this mentally as a soda fountain. So quick pro tip, you can actually segment your streams into kind of standalone substreams so that you can compose them together. So just throwing that out there I've taken a left stream and a right stream.
[00:05:46]
And what I'm doing so these are my initial outputs plural is that I'm going for the left and right button. And when my left button is clicked, I'm returning a negative 10, when my right button is clicked, I'm returning a 10 and then all I'm doing is in this merge operator is I'm saying take either one of these.
[00:06:11]
And if anything, admits it, put it into this merge stream and pass it down. And so, within this then it just works just like the previous method over here that were either adding 10 or adding negative 10, which is the equivalent of subtracting. So we're able to now express this by simply segmenting and capturing two initial outputs, and then just merging them together.
[00:06:38]
So what does this look like? Well, right, left, but what I think is interesting about this, is that within this, the code that handles either stream is exactly the same we're not changing that. All we're doing is just passing in a different stream or getting the same output.
[00:07:07]
So notice we're now merging two streams together to produce a single stream that we can act upon. Now this is a brain bender, this is fun so, again, we are incrementally building, and I'm gonna just drop this little nugget in here what can we put in a stream?
[00:07:33]
Up to this point, we have been dealing with permanent values so, we are using a stream to communicate essentially primitive values and objects. Is it possible that we could actually communicate future behavior to be executed at some point in. The future down the road, and the answer is absolutely.
[00:08:04]
This was a big elaborate setup to get you to this point right here today. So, what we have in this code is we have some inputs or some outputs rather and let me go, well, I'll leave this here for now and then we'll kind of look at the code and poke around.
[00:08:26]
That we have left arrow and right arrow, and what is this doing? Well, our initial output is we're listening for a keyboard event and we're filtering out Is this a left arrow or the right arrow? And then from here, we're calling map to and we are returning something.
[00:08:56]
All right? So we are returning a result, and in this case we're calling decrement, or increment and we're passing in two of the three parameters that Exist on this parameter signature, so now the question that I have for you is what are we passing in the stream? The answer is a partially applied function, we are sending a function with two of the three parameters satisfied so that when you call that function, so it's returning essentially a function that you can call which you can see here is we're calling current.
[00:10:03]
And we're parsing in the accumulated value, so essentially we're parsing a function into the stream that we're then calling in our scan operator. So, just to let that sit, we have the ability in JavaScript to essentially define functions that you can pass around that are partially applied that when you supply that last parameter, then you can then call it, so the result is actually a function that you can call.
[00:10:42]
So this is Similar to function curring, but it's a little bit different. The point is that we are able to now determine dynamically that when I call, left or right, up or down, I'm going to return a function that I'm going to call in my scan operator, which is an ultimately going to determine the result of the position that gets put into the DOM.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops