Transcript from the "Basic Sequence" Lesson
>> Lukas Ruebbelke: Now I would imagine that most of us are pretty familiar with kind of concept of, I have some input, I'm going to produce it to you, and you're going to give me some output. So input, output. I think everybody here is like, okay, I understand that concept.
[00:00:17] But what I would recommend for observables is flip this in your mind, to this. And I owe all the credit, I don't want to by any means try to hint that I came up with this, this was actually John Lindquist sat down and explained this to me one evening, and this is basically what he told me, is that traditional programming, you're used to essentially providing input and pulling the output to you or requesting output.
[00:00:46] I'm gonna give you this thing and you're gonna give me something back. With observables, the output is happening. There is a stream that is always outputting data, and you simply need to figure out where you're going to put it. And so instead of having initial input to get final output, reverse that to think of, I have this initial output, in other words the start of this stream, and my job is to figure out where I wanna put it and what form it needs to be in when it gets there.
[00:01:20] So, for instance, if you are consuming a Firebase end point, so Firebase is a real time database that as things change in the database, it will push them out to you. So any connected client, if something changes at the Firebase database, it gets basically pushed out to any connected client.
[00:01:40] Well, that Firebase stream is happening all the time, it's streaming whether you're connected or not. But, once you're connected, you now have hooked into the output of the stream. You need to figure out where you wanna put it and what shape you want it to be in. And so this is the basic sequence of an observable stream.
[00:02:05] We have an initial output. And at the bottom of this, we have a final input. And in between, we just have some magic that's going to happen. So I call this pretty much the observable sandwich, if you will. The reason why I also call it final input, is because once it hits your subscribe block, it is in its final form.
[00:02:31] The observable stream can no longer do anything with that data. So it is kind of the equivalent, if you have a garden hose, you turn the knob, water's coming out. So that's the stream. You need to figure out, where am I gonna put this? Am I gonna put it in the flowers, the grass?
[00:02:49] Spray my dog, whatever. But once it's off the end of that hose, that's it. You can no longer control it by means of the hose. And so that's why we say final input. So initial output, so you have the stream, the genesis of it, it's coming through your what I'll say magic, I'll clarify this in a second.
[00:03:11] And then now you're trying to decide, where do I want to put it and what is the final form going to be? So in this case, more often than not, you have an event. Then you have some kind of operator or operators, which I can't wait to show this to you.
[00:03:28] And then a subscribe block. So the event or the start of the stream is your initial output. The final input is your subscribe block. So that's no mystery there. In between, we have tons of operators at our disposal to control what form our data's going to be, or what is going to come out of that stream when it gets to its final destination.
[00:03:59] When I started working with observables, because I was used to promises which do not have any operators, I would get into my subscribe block. I'd be like, I got this thing from the server, then I'd be looping over it and fiddling with it. And I realized, if I get to my subscribe block, and my data is not in the exact shape that I want, in other words, I can't say, take this result and just assign it right into a local variable, I am not using it properly.
[00:04:27] Your data, when it hits the subscribe block, it should not only be in the final input but it should be in its final form. And so this is where these operators come in in a really big way. And so, with that in mind, when I look at an observable sequence, or something that's happening with an observable; I work through it in this way.
[00:04:54] What's my final or my initial output? Where's the start of this? What's my final input? And then I work kind of in the middle and I figure out what's actually happening in the stream itself. So let's work the system. Initial output, in this case we're capturing an event.
[00:05:14] And we're saying create an Observable from the click event on this button. And so I have a little helper function to kind of unwrap it so I can get the native element. But what's interesting, I didn't really think about this until I started working with observables, user interactions are the ultimate streams.
[00:05:37] Your DOM, your browser, is emitting events every single, anytime you interact with the DOM, you move your mouse, anything. User events, user interactions it is a constant stream of data that you can capture and do things with. Even, for instance, a button, that's not a one-off. Somebody can click a button a bunch of times.
[00:06:00] Well, wouldn't you wanna capture every single click on that? And so this is where, and we're gonna kind of focus initially on some user elements, is that capturing user interactions and transforming them via an observable stream, is really, really neat. So here, our initial output, Observable.fromEvent. We're saying take this button, and create it on the click event.
[00:06:27] So, I mean, it kind of looks like an event handler, basically. And our final input. So we're just saying take this event. So this is an actual DOM event. And we're not actually doing anything, we're just saying okay, when this thing happens, we're saying this message equals Beast Mode Activated.
[00:06:49] But I'm going to teach you a very valuable lesson here. That when life give you lemons, map it to lemonade. So we're getting this event, it's a DOM event. We don't care about that. It's not what we want. What we want is we want to send in a message into our subscribe block.
[00:07:13] So in this case we're saying, take this event, and instead, I want you to return this. So we're taking the event, we're just returning a string. So sometimes it's as simple as a straight swap.
>> Lukas Ruebbelke: And you can stack these operators to do multiple transformations. So this works in a very kind of pure pipe, functional ways is the word I'm looking for.
[00:07:43] So these functional operators, because they have no side effects, complete referential transparency, is you can stack these together. So in this case, we're adding in a filter. And we're saying, only allow events through the stream if the Shift key is held down. So we're filtering out anything that doesn't meet our criteria.
[00:08:05] And once it is held down, it says, okay, good, we'll let this event pass through. And then we're saying, okay, take the event and instead map it to this string and pass it down the line. So you can think of this as almost this super highway that only you can drive on.
[00:08:21] So it's completely encapsulated. And as you're driving down the highway, you've got these mini factories along the way that's saying, pull in, it does some transformation, pull out, some additional transformation, until you get to the end of the road. So let's do a demonstration and kind of start to build on this and see what comes of this.
[00:08:44] So my goal is as we type along and do this demonstration, please follow along, that we will have a sense of one, initial output, final input, and then we'll start to stack in some operators and see what we can make of it.