Check out a free preview of the full Asynchronous Programming in JavaScript (with Rx.js Observables) course
The "Observable Filter Function" 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:
The Observable filter function has a similar implementation to the map function. Jafar leads the group through adding this function and explains the public forEach function with a little more detail.
Transcript from the "Observable Filter Function" Lesson
[00:00:00]
>> [MUSIC]
[00:00:03]
>> Jafar Husain: So there's a mapped observable in ten lines. It's not a lot of code.
>> Jafar Husain: Should we try a filter? Let's see if you guys can help me write a filter. You know how filter works on array? So filter takes not, it's not called a projection function it's called the predicate action, who cares about the fancy name.
[00:00:29]
Let's just call it what we all know it to be, a test function. It returns true or false based on the object going in. And so now her job is to be a filtered observable and I'm the source observable, right. And he's going to call forEach on her and her job is to make sure not to give you any numbers larger than five, okay.
[00:00:51]
So you're only gonna get numbers smaller than five, right so let's try it again, forEach her.
>> Speaker 2: Okay, so but I'm forEaching a function, right, and that function is gonna have that logic built in, right?
>> Jafar Husain: Well, so she's the observable that is the result of calling filter on another observable.
[00:01:08]
So when you call filter on an array, you get an array back, right? When you call filter on an observable you get an observable back. So let's say you, I'm the source observable. I'm just gonna, on next number, number, number, number. You filter me and you create her, she's now a filtered observable that's holding on to me, she knows how to talk to me.
[00:01:25]
And when you foreach over her, she's going to foreach over me because in order to give you my filter data, she has to ask for and that's how she asked for it. She foreach's over me. Okay, so let's play it one more time. Filter right, we're gonna do it live and I'm like well with acting it out and then we gonna code it up and we'll see the correspondence.
[00:01:43]
So foreach over her.
>> Speaker 2: So foreach over the observable.
>> Speaker 3: Sorry.
>> Jafar Husain: It's okay.
>> Speaker 3: Foreach.
>> Jafar Husain: Right, she forEach's over me. I say, on next one, you're only gonna give him numbers, larger or smaller than five, excuse me. So one.
>> Speaker 3: On next, one.
>> Jafar Husain: On next, seven?
[00:02:03]
>> Jafar Husain: On next nine? On next three?
>> Speaker 3: On next three.
>> Jafar Husain: On completed.
>> Speaker 3: On completed.
>> Jafar Husain: So she's only, sorry?
>> Speaker 2: Dispose.
>> Jafar Husain: Well, you don't call dispose. When she says to you onCompleted, you don't have to call dispose. Why would you call dispose? She's never gonna call you again, right?
[00:02:19]
It's her job, that when she says onCompleted, she cleans up after herself. So there's no reason for you to call dispose.
>> Speaker 4: She's gonna call dispose?
>> Jafar Husain: Under the hood, yes. Technically she calls dispose or at least does everything that would happen when you call dispose. Her job is just to clean up after herself so that she's never holding on to any of his references.
[00:02:37]
Does that make sense? So let's try it. So let's try it now in code, right. Before this was a mapped observable and now it's a filtered observable. So this is the filtered observable. This is the original source of observable which we're capturing by of ourself equals this. And now when you foreach over it inside of the on next.
[00:02:59]
What are we gonna do? Where there was a map, we just applied a function to it and then took the result and threaded it on through. But what's different about filter for map?
>> Speaker 3: You're comparing, there's a test.
>> Jafar Husain: There's a test function. So we need to take the data, that I'll on next her, like nine and we need to run it through the test function, right?
[00:03:24]
And then how does she decide whether to on next him?
>> Speaker 2: If text function returns true she will on next him, the thing whatever it is-
>> Students: [LAUGH]
>> Speaker 6: The value.
>> Speaker 2: The value.
>> Jafar Husain: We don't translate the value, right? Filter doesn't change values. It just decides whether or not to forward them along, right?
[00:03:56]
So I got a few errors are probably missing semicolons.
>> Speaker 2: So is that basically what we wrote when we implemented filter?
>> Jafar Husain: For array, yes. You did the equivalent for an array. If you think back to what you did over an array, you for eached over, right. And then if it was true, you ran it, if you go back and even look at your definition of array you'll see the correspondence, right?
[00:04:16]
You for eached over the source, and if it happened to run through a test function and returned true, you would send it along. In your case, you would put it into the new array with results.push. In our case, we don't we're not accumulating up data in a big array somewhere.
[00:04:28]
It's actually a good deal more efficient. Imagine, if you take one, two, three, four, and then you map over it, and then you just add one to everything, you're creating a whole big copy of that array in memory. Not so with observable. We don't create big copies of streams in memory, every single time I give her a value she doesn't stored anywhere.
[00:04:46]
She just forwards it on to you like a hot potato. So when you create map filter, when you create this big expression of observable you know what you actually really created? Just a tiny little object graph in memory of functions holding onto functions, holding on to functions, holding on to functions.
[00:05:02]
It's very little memory compared to if you map over an observable with 12,000 items in it, if you map over an array with 12,000 items in it you get a whole another array exactly as long. This is the notion of streaming data through, right? We're streaming, we're not collecting it up in memory.
[00:05:17]
We're streaming it through. So, you want to take this out for a spin? Let's see if this actually works. Let's see if we can get, maybe we can like map mouse positions or something. Why are we.
>> Speaker 7: I'm sorry, I'm confused about forEach, because we're declaring a new function named forEach within the function definitions here.
[00:05:40]
And then we're calling salt.forEach underneath that but the salt.forEach is a different forEach than the forEach-
>> Jafar Husain: Yes.
>> Speaker 7: In which we're defining. And then we have _forEach. So there's three different forEachs?
>> Jafar Husain: Right, well, the _forEach isn't too important, the whole point of this whole wrapper object, this wrapper forEach's job, it's the public forEach.
[00:05:59]
We all ways call the public forEach, and it's always the same definition? All it does is it checks to see whether you're passing in an observer object or you're passing in the three call backs. And it's whole job is just to always turn it into an observer object.
[00:06:11]
And then it calls this underscore foreach. The underscore for each is the one that we're passing to the constructor and that way when we define what observable is, we're not to worry about the two different possible overloads. Maybe they're passing in functions, maybe they're passing in observers. We always get to write our observable definitions, assuming that what gets passed into our forEach function is an observer.
[00:06:32]
So that's the whole purpose of this function here. It's just to sanitize the input to always turn it into an observer. So when we write new observables. We only ever need to worry about observers we don't to worry about. Maybe the past three callbacks or maybe the past the observable and so.
[00:06:45]
>> Speaker 7: That's when we call and we say self.forEach.
>> Jafar Husain: Yes, when we say self.for. Well I want to be clear when we call self.forEach.
>> Speaker 7: In that context.
>> Jafar Husain: In this context we're calling the outer foreach this is the foreach, right. But then it immediately inside. We invoke the underscore for each which is what we pass to the constructor.
[00:07:06]
This is just an identifier name to help us understand that I'm just that I could take I could delete this foreach right here. It's just there to help you understand that that's the definition of the function right here foreach. Yeah, question at the back.
>> Speaker 8: What name is there?
[00:07:17]
>> Jafar Husain: Totally optional. I can name this blah, blah. Question in the back.
>> Speaker 9: You might have answered it, but why are we naming the function we are passing to the observer [INAUDIBLE].
>> Jafar Husain: Purely for clarity. Just so you guys know, otherwise there'd just be a, sort of a function, without a name floating around here.
[00:07:31]
It's just so that you know that the function that we pass inside of an observable is the definition of forEach. That's why I'm naming that function. Otherwise, if I don't name that function, I've found in the past, people kinda get lost. They're like, what function is this? Cuz let's face it, we're dealing with a lot of functions.
[00:07:44]
We're not dealing with a lot of code. Notice, there's very little code here, right. But we have some nested functions. So you've got to get, part of this exercise will be getting really good with understanding function scope, right, and what it means in JavaScript. But as you can see, it's a pretty powerful technique.
[00:07:58]
Cuz we haven't written very much code, but we've written some very powerful functions. So let's try this out on a real dom object and let's see if this works. Maybe even the first time, but more importantly, it's not so much about writing code. We've already shown you what you can do with observable, right?
[00:08:12]
You can build really powerful asynchronous programs that clean up after themselves. The point of this exercise is to actually walk through the code and see what's happening underneath the hood. Which will really deepen your understanding of what's going on when you use these functions.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops