Check out a free preview of the full Asynchronous Programming in JavaScript (with Rx.js Observables) course
The "Observables and Events" Lesson is part of the full, Asynchronous Programming in JavaScript (with Rx.js Observables) course featured in this preview video. Here's what you'd learn in this lesson:
Before starting exercise 32, Jafar spends some time explaining how to respond to UI events wrapped in Observables. Execution code is placed inside a forEach so it can be run each time a new event is added to the collection.
Transcript from the "Observables and Events" Lesson
[00:00:00]
>> [MUSIC]
[00:00:03]
>> Jafar Husain: So all the map and filter and zip and reduce stuff all works over observables.
>> Jafar Husain: This one's fun. So we're gonna create that mouse drag event. But first, we're gonna start with an example that you guys already know. Or a similarly example you guys have been working with last few days.
[00:00:25]
Let's take this example and let's slowly morphed it into a mouse stagnant. So what do we do? We've been going through this the stuff I'm not easy at all. Yesterday, we went through movie lists, and then we went through videos. But we filtered the videos collection before we returned it.
[00:00:41]
And then we ended up with a two-dimensional array. And then we used contact map to flatten that by one level. We just that's what we were doing again and again yesterday. So let's see why we've been doing those wax-on, wax-off exercises. Now I'm gonna slowly change this.
>> Off Camera 1: A console log in that filter function that it would do nothing until for each is called?
[00:01:22]
>> Jafar Husain: That is absolutely correct, not a bit of code in here. Well excuse me, not a bit of code inside of the handlers, right? Because handlers are, like the filter code, right? This code is only gonna execute when data makes its way through. And we're only gonna start getting data.
[00:01:40]
The way to think about this is, actually here's a good way of thinking about it. The event handler has not, remember when you adapted the buttons clicks to an observable? That did not hook up an event handler. The event handler is not gonna be hooked up until you actually call forEach.
[00:01:54]
Because what happens and what we're gonna later on, it's gonna be fun we're gonna actually implement observable. So you can see all the in ads inside and how simple amazingly simple observable really is. And we're gonna step through the code and we're gonna watch what happens when you call forEach.
[00:02:07]
We're gonna follow it all the way up to subscribing to the event. First, I wanna make sure your proficient in using it. And then later on, if we have time, we'll actually just implement a mini-observable and all those map and filter and from event and that type of thing.
[00:02:20]
So you'll actually be able to follow up follow up the progression, but that's what happens when you call for each one of observable. Lets say I take an observeable and I mapped it. Well, when I call for each on that observable, it calls for each on its data source.
[00:02:31]
And that'll call for each on its data source, and on and on and on. Up until finally we reach that observable that adapted from the button clicks, and then it'll call addEventListener(). Does that makes sense? So an observable's a little like an event, but it's also a little like a function.
[00:02:45]
It's like an event in that will push your data, but it's more like a function in that it won't do a thing until you call it. Does that make sense? Until you call that one forEach function. So we're gonna try and leverage all the metaphors for how you're already used to thinking here.
[00:02:57]
And I'm gonna combine them and meld them together to get a good idea of how observable works. So now we've got, I was just in the middle of changing this. So filter takes a collection, and potentially makes it smaller. We'll take until does the exact same thing. It takes a collection and then makes it smaller.
[00:03:17]
Just slightly we just use it by instead of applying a function to each item, right to see whether passes a test or not. Instead it listens to another observable and it completes the source observable when that other observable fires. And so mouse drag. All that stuff about processing data.
[00:03:37]
Remember we talked about why we use map instead of zip? Well, I have to process the video lists before I process the videos. Well it's order, right? You can use map to enforce order of events. That's what we're doing here. We're saying, well, I'm gonna listen to the mouseDowns first.
[00:03:53]
And then when I get a mouseDown, I'm gonna go through the mouse moves, right? Before we had to do that with an array because well, you can only get to the videos by going through the video lists. But here you can also take two, we noticed when we did our example where it's relational where we had ID's where we had two collections of the same time In order to create the structure we wanted we just chose in which order to map through.
[00:04:14]
What we said, well I wanna create lists that contain videos. So I gonna map through the lists arrays first. And then within there, I'm gonna map through the videos array, so that was the relational example where we link stats links up by IDs. So we were creating the structure we wanted by imposing an order.
[00:04:28]
Sometimes an order is imposed on us Like with the the video. Listen, it contains the videos and then we have to map a nest through. But sometimes, we just have access to two collections at the same time and the order is really up to us. If we map through the former before the lot or we get one structure for building a tree.
[00:04:43]
If we swap that around, we can get the other structure. That's really more akin to what we deal with when we deal with observables. Usually I have access to the mouseMove. In this case I have access to the mouseMove event, I have access to the mouse event, mouseDown event all at the same time.
[00:04:55]
In order to get the, in order to enforce an order, I just choose in what order I map through them. But if I map through mouseMoves and then mouseDowns. Well, then I wouldn't start listening for a mouseDown until a mouseMove came along. Does that make sense or is that worthy of a little more, little more hammering home, right?
[00:05:13]
Because here, I'm gonna write this the long way first. Right because remember that's all that's going on. Can always switch a concat map to a map followed by contactAll(), right. This function right here is only gonna get called when we get a mouseDown, right? When a mouseDown arrives in that collection over time.
[00:05:33]
And so therefore, we're not even gonna begin listening to mouseMoves until a mouseDown comes along. Because how would we? This function's not even gonna get called. It can't get called until a mouseDown comes along. So when a mouseDown comes along, we execute this function. And we return that new collection and concatAll and concatAll.
[00:05:52]
The thing responsible for flattening. So it sees a two-dimensional observable. And every single time an inner observable comes along it's gonna for each over that right. And this right here is the inner observable. So first, we see the concrete all subscribe to the outer observable which is mouse downs, right?
[00:06:09]
And then a map, and then every inner observable comes along. It's just gonna be all the mouse moves until the mouse up. So then it subscribes to the inner observable, and that's how we enforce order. I wanna listen to this event happening before I listen to that event happening.
[00:06:22]
Does that make sense? So if you've just got a bunch of events and you wanna order them, map, right? If you want to listen to them up the same time. What do you think the operator would use? We're listening to two events in exactly the same. Any time you get an item from each side, you wanna do something.
[00:06:41]
Let's say you got two network requests and they're both observables of one and you wanna wait for them both to finish before you do something else. What's the operator I would use?
>> Off Camera 2: Zip
>> Jafar Husain: Zip, now we know why we learned zip, right? Zip, the truth is when you're doing programming most of the times in arrays items don't happen to be organized by index.
[00:06:59]
It's actually very rare. Usually, they're organized relationally by they're linked together by some ID or they're organized hierarchically. And so I'm the first to tell you that when it comes to arrays. Zip isn't that useful [LAUGH]. You're probably not gonna use it very much. When it comes to asynchronous programming that's probably the most common usage.
[00:07:14]
When you're dealing with concurrent network requests, right? It's very often that you have maybe even two or three network requests and they're all gonna give you one result. Zip is perfect for that, right? Because you can zip, you just wait for them all to be done. And then your function gets called with the results of all of the different observables of one all at the same time.
[00:07:31]
So you can make a request, concurrent requests to three different services. And then take the results and combine them together into some object that's a composite of the data from all three. So that's where as zips gona apply, right? So we've seen how we can order events using map, right?
[00:07:46]
Filters, self-explanatory, the same thing with arrays and observables. Sometimes you're only interested in a certain type of event or an event that matches a certain condition, right? I'm only interested in listening to this mouse move when it's within the bounding box of this button right that's what filters for.
[00:08:00]
And it corked out all the same thing really. You have nested observables and you wanna flatten them, right? To make sure. Because in the end, what are we gonna do at the very end? Once we've built the observable, we want what's missing from this code. In this code, we're not gonna hook about event handler.
[00:08:16]
Not even an event handler's gonna be hooked up, nothing is gonna happen. What do I have to do to actually make this code work? To actually listen for mouse tracks?
>> Off Camera 3: ForEach.
>> Jafar Husain: ForEach, yes. All I did here was created observable and that's just like a function waiting to be called haven't done a thing.
[00:08:33]
I just created a function that I can call later if I want to and how do I call it?
>> Jafar Husain: I'm cheating a little bit here.
>> Jafar Husain: Let's not cheat.
>> Jafar Husain: I think it's clientX and clientY.
>> Jafar Husain: Now I'm actually going to be listening. It's like I've created this event, but I'm not listening to it.
[00:09:22]
But now that I'm listening to it, I can do something. Notice the one changing an object that I didn't create here. That's what's happening in do I'm changing the world. Now I've created a stream of the events of interesting events. I'm gonna traverse that collection and do something with the information I'm gonna change things.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops