Check out a free preview of the full Asynchronous Programming in JavaScript (with Rx.js Observables) course
The "Creating Collections" 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:
Jafar demonstrates how to use the functions he introduced in the previous section to create useful collections from a data source. He then applies the same code to a mouse-drag scenario to illustrate that events can be handled in the same manner.
Transcript from the "Creating Collections" Lesson
[00:00:00]
>> [MUSIC]
[00:00:04]
>> Jafar Husain: Who here is a Netflix user? Great. All right, that's what I love to see. The Netflix model is pretty simple. When you go in, you get merchandise a list of genres, and within those lists of genres we recommend you a list of titles. So let's try using map and filter concatAll to get a list of your favorite Netflix titles.
[00:00:27]
>> Jafar Husain: Here's how you would do it. So I wanna create a function called getTopRatedFilms and that's gonna accept a user object. And every user object has a videoLists array, that's just the array of genre lists that you saw earlier, the action movies, thrillers. We're going to map over all of those video lists, and before we return the video of this we're first going to filter it to make sure all of the videos, we're only returning videos with a rating of five.
[00:00:53]
Now because for every video list, notice we're returning another collection, right? Notice the function being passed to map returns videoList.videos, which is another array. That means we have a two dimensional array and we apply concatAll to it to flatten it down into a nice flat list of your favorite titles.
[00:01:13]
Does that make sense? Should we go over that just a little bit, or do we feel pretty good about it?
>> Jafar Husain: Any questions?
>> Off Camera 1: Why is it 2D?
>> Jafar Husain: Why is it 2D? Well remember we're starting with pretty much, it's kind of like a two dimensional collection because we've got genres and within that we have videos.
[00:01:35]
Right, so first we're mapping over the outer array, the genre lists array. And then with that function that we're passing the map, its job is to take each one of those arrays and translate it. And what are we doing? Well, we're just returning the videos array, but first we're just filtering it.
[00:01:50]
And so that means for every array, we're just returning a filtered version of that array. Does that makes sense? Technically it's an object with an array inside of it. That's the videoList.videos, but you get the idea, right? For each one of these video lists, which contains an array we're returning that array, but first we're applying a filter to it.
[00:02:05]
And we're just making sure that all the titles are only the titles you've rated highly. And so at the end up until the concatAll line, we have a two dimensional collection. At the end we apply concatAll and that's what takes that two dimensional collection and flattens into one dimensional collection of your favorite titles, all the titles with a rating of five.
[00:02:21]
Yeah?
>> Off Camera 2: So you mentioned that we had just a normal for loop, it's not going to work asynchronously?
>> Jafar Husain: Yes.
>> Off Camera 2: So, if we had this and let's say it starts with three items and it starts running through, and then after it's done concatAll, we get the fourth item.
[00:02:36]
Does it run through again, or can you explain how it works asynchronously?
>> Jafar Husain: Well so I'm not going to talk about asynchrony at all yet.
>> Off Camera 2: Okay.
>> Jafar Husain: This is just arrays. We are just working with arrays here. So a for loop would work just fine to be honest.
[00:02:48]
>> Off Camera 2: Okay.
>> Jafar Husain: But the goal what we're doing and why we're talking about arrays at all, is we're trying to take a data structure you guys are already familiar with and feel comfortable with. And learn how to use these functions over this data structure. Before we tackle a very different, but not so different, data structure where we introduce asynchrony.
[00:03:04]
So it's just arrays.
>> Off Camera 2: Okay.
>> Jafar Husain: We can try this right now.
>> Off Camera 2: I'm with you.
>> Jafar Husain: So now I'm going to ask you a question, which is what if I told you you could write nearly the same code to build a drag and drop event. So I'm gonna show you a little preview of what we're gonna be covering, and what you can do if you start to get good writing programs with these few simple functions.
[00:03:24]
You can take them and not just use them for arrays, but also on asynchronous data sources like events. So I want you guys to look really carefully cuz if you blink you're gonna miss it. Okay, so here we are, we're processing your favorite titles, and here is how you build a mouse drag.
[00:03:42]
I want you to notice the structure of this code is almost the same. What is a mouse drag? Well, it's all of the mouse moves that happen between a mouse down and a mouse up, right? Imagine for a second that events weren't this weird thing that you call with an addEventListener or a removeEventListener, this sort of quasi object hanging off of a DOM.
[00:04:07]
What if they were first class values that you could hold onto, just like arrays, and they had methods on them, just like map and concatAll and filter for that matter? We could actually compose together events to build new, more complex events using these methods. So imagine we have a collection of all of the mouse downs on a DOM element from now until eternity.
[00:04:30]
And we just map over it. And we map over all of the mouse downs that happen on a DOM element, like a button for example. And every single time we get a mouse down, we then return it, we map over it and for each mouse down, we return all of the mouse moves that are detected on the document level.
[00:04:47]
Reason why we list the document level is we're looking for for bubbling, right? So when I start moving around the button, my mouse might go faster than the button. And so by the time I've begun a drag operation, we wanna be listening at the document level for mouse move just in case my mouse gets ahead of the button so that we can move that button around.
[00:05:01]
Hopefully that's clear. So we're literally replacing, cuz what map is all about it's about replacing. So for every item in a collection we wanna replace it with the result of this function. So in this case, we're replacing the actual mouse down event. That little event object, you would get if you did an add event listener with all of the mouse moves from now until eternity.
[00:05:20]
But instead of just returning that whole collection, which would go on forever. In the previous example, we saw that we use filter to take certain a collection and reduce the number of items inside of it. Here we're gonna replace the filter method with a takeUntil method. All that does is, it takes some stream and another stream and it listens to the source of some stream of information an event, mouse moves in this case, until another stream fires.
[00:05:46]
So I might be listening to a mouse moves event and the mouse up event, and I'm just going to keep forwarding on all those mouse moves, until the mouse up event happens and then I'm gonna unsubscribe from both the mouse moves and the mouse up. So what we've done is create a collection.
[00:05:58]
We've taken two collections which go on for eternity, and we actually combined them to create a collection that ends. Because we listen to one collection until the other one fires and that's what takeUntil does. So just like filter reduced the number of items in the collection, takeUntil reduces the number of items in collection.
[00:06:13]
What it does is it creates a collection of all the mouse moves until the next mouse up and then the whole collection ends. So for every single mouse down we're gonna return, we're gonna replace that mouseDown object in the stream, with another stream of all the mouse moves until the next mouseUp.
[00:06:30]
Now notice that I've taken every item in the collection and I've replaced it with a collection, which means I have how many dimensions of collection? So if I take one, two, three and then replace each one of those items with another array, so I have an array of 5 6, an array of 9 7, and an array of 4 8, how many dimensions is my collection?
[00:06:51]
Two, right, cuz every mouseDown object that we got we replace with a stream of all the mouse moves until the next mouseUp. And so how do we flatten a two dimensional collection? ConcatAll. Yep?
>> Off Camera 3: There's a question, where you concatAll come from?
>> Jafar Husain: So contactAll doesn't exist on the JavaScript array.
[00:07:10]
We're going to write it ourselves later. And it does exist on this data type, the magical data type I'm going to teach you about that lets you code this way, because obvious this will work over arrays, right. You can't model an event as an array just not possible to do in JavaScript because for one thing events go on forever, so you'd run out of memory if you try to do that, right.
[00:07:26]
So I'm going to teach you a new data type later on with the exact same APIs that I'm going to teach you to use over arrays. And so we're going to introduce concatAll onto array today in our exercises, and then later on we'll show you how to write concatAll over the data type that I'm going to reveal to you very, very shortly, which is what makes this possible.
[00:07:43]
But we can see that structurally at the same level, if we just think about events as a collection, we should be able to do this. So the top half of the slide is all about taking the events that we have in our system, the primitive events that we have in our system, and composing them together to create more complex events.
[00:07:59]
Now this is something we do with functions all the time, right? You take function A, function B, compose them together to create function C. You create function C, which calls A and B. But for some reason, when JavaScript programmers do event-based programming, they don't do the same sort of compositional style, and that's wrong.
[00:08:13]
We should approach events with the same sort of approach to composition that we do with functions. And that's I'm gonna teach you how to do today. It's a very powerful technique for controlling the complexity involved in asynchronous programs. I think you're gonna be really shocked by what we're able to do with just a few simple functions.
[00:08:29]
So the top half of the slide is just creating the stream of mouse drags. It's actually creating, taking a function which when given a Dom event, will return a stream of all of the future mouse drags that happen on the DOM element. In other words, all the mouse moves that happen between a mouse down and a mouse up.
[00:08:45]
Now that's the top half of the side. All we've done is we've created a stream when a function gets called. The bottom half of the slide actually uses forEach to consume the data inside of the stream and do something with it. Increasingly you're going to see as you write code, your code will begin to bifurcate into two parts.
[00:09:04]
Building the collection that you want, and then consuming the data in that collection and doing something with it. The bottom half of the slide is morally equivalent to addEventListener. It turns out that adding an event listener isn't so different than forEaching over an array. What are you really doing?
[00:09:19]
You're just consuming each item in a collection as it comes in and doing something with it. So here in this particular case we're actually gonna move the position of the image, so that it actually drags around. You're actually see this code in action later on, it's pretty impressive.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops