Check out a free preview of the full Asynchronous Programming in JavaScript (with Rx.js Observables) course:
The "Observable Metaphor" 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:

While addressing an audience question, Jafar provides a real-world metaphor to further explain the difference between observers and iterators. He also walks through the implementation of the Observable.fromEvent() method.

Get Unlimited Access Now

Transcript from the "Observable Metaphor" Lesson

>> [MUSIC]

>> Jafar Husain: You had a question?
>> Speaker 2: I like to understand things in very simple analogies, so I wanted to check my analogies with you to see if it's correct. So an iterator function sounds to me a lot like a paper feed on a printer. Is there is a piece of paper?

[00:00:16] Yes, print. Is there a piece of paper? Yes, print. So it's empty, error.
>> Jafar Husain: Yep.
>> Speaker 2: And an observer would be like somebody cutting pieces of birthday cake, handing it to the person, person just keeps handing pieces of cake down to other people until they get the piece they keep themselves.

[00:00:35] They don't need it anymore, or if you're Milton, you don't get the piece of cake. [LAUGH] And just get the air.
>> Jafar Husain: Sometimes it's tough to express it as metaphors because the truth is, you can think of that as both a push or pull, right. Really it's all about who makes the decision when another value is delivered.

[00:00:52] So why don't we anthropomorphize the iterator and observer pattern and why don't I be the producer and you be the consumer. And let's say we're distributing cake, and you decide you want some cake. So what do you do? If it's iterator, right, what you say to me is, look I wanna start asking for cake and maybe I'm gonna distribute it to folks, right, but I'm gonna be first.

[00:01:11] I'm asking you for cake. And so the way it works is, you say, can I have cake, please? So you start, notice she's starting, she's gonna consume the cake and she started, right. And so you say.
>> Speaker 2: Can I have cake, please?
>> Jafar Husain: Sure, I cut her a piece of cake, I hand it to her, right, and then I wait for you to-

>> Speaker 2: Can I have cake, please?
>> Jafar Husain: Right, cut her another piece of cake, hand it to her. We're running out of cake, right, I hand it to her.
>> Speaker 3: Say it again.
>> All: [LAUGH]
>> Speaker 3: Now he's gonna get to run out of cake now, and that's what's gonna-

>> Jafar Husain: That's the next step, yeah.
>> Speaker 3: You can just keep asking.
>> Speaker 2: Can I have cake?
>> Jafar Husain: Yes, you may. No, I've given you some cake, but now, I'm out of cake. So I'm gonna also tell you, by the way, I'm out of cake. I got no more cake for you, right.

[00:01:53] So that's the iterator pattern. What is the observer pattern? I cut some cake and I throw it at her. I don't even wait for her to be ready, right. She's like, okay, give me some cake. And I'm like, I'm just throwing cake at her as fast as I can possibly throw it, whether she's ready or not, right?

[00:02:08] So I'm in control, I decide when she gets cake. And then when I run out of cake, I say, no more cake for you. At this point you're probably happy, right? Nobody throwing cake at you, now that we've anthropomorphized the patterns just about who's in control. Are we pulling, is she pulling?

[00:02:24] Or am I pushing? Does that make sense? But either way, we distributed cake, right? We got it done. We got cake from point a to point b. So all we're doing here, is we're adding the ability then, those last two functions, for me to tell her no more cake.

[00:02:41] Or I guess the error would be like I cut my finger, or something, something went wrong. So that's how I would communicate to you that I cut my finger, I can't cut you any more cake. That's the error. Or we're out of cake, nothing there. And the first callback is just for sending the cake.

[00:02:56] Does that makes sense? So now we kind of get what the observable type is, right? It's just another way of getting information from point a to point b, except you're not in control, the producer's in control. And so here's the overload that you can use if you wanna pass in an object.

[00:03:08] We'll be using this overload in our examples here, okay. But that's from now on when I talk about the observer object, this is what I'm talking about. An observer observes an observable, it's the object with those three methods on it. So I might be mentioning that a little bit later on.

[00:03:22] Another question?
>> Speaker 5: Are you limited to the onNext, onError, onCompleted, or can you run, I guess actually on your next slide, I think.
>> Jafar Husain: That's it. Well, it's the same semantics that we have with the iterator, right. It's like that's what we're trying to do with this protocol.

[00:03:37] You can find a million ways for getting information from point a to point b. But what we're trying to do is come up with a very strictly defined way of getting information from point a to point b, and it's got three semantics. I give you data, I tell you an error occurred, and I tell you something completed.

[00:03:51] You'll be amazed what you can actually do with that very simple protocol. Turns out it's enough to get the job done. Okay, so here is the function that we use to convert a DOM event into an observable. So it's actually a static function that we just hang off of the observable type.

[00:04:10] So you just call Observable.fromEvent, and you pass in a DOM object and an event name. An observable is nothing but an object with a forEach method. Every other function that I'm gonna teach you about today, map, filter, concatAll, all of them are implemented in terms of for each.

[00:04:27] And so if you wanna create an observable, all you gotta do is create an object with a forEach method. Because, of course, forEach is how you get the data out, right? So if you give an observer to the forEach method, it's just gonna push data at you. So if you wanna create, yeah, another question back there?

>> Speaker 5: Yeah, what does the dispose method do when the producer indicates it is done sending events?
>> Jafar Husain: Under the hood, what the dispose method means is that you're not gonna get any more callbacks. I'm gonna stop throwing. So we left out that little piece of semantic, right, which is I'm throwing cake at her and one thing she could understandably say is, whoa, whoa, no more cake, please!

[00:04:59] Right, and that's different than me saying I have no more cake left, right? She's just saying, I don't want any more cake. And that's effectively what the same thing is when you call dispose on the subscription method. It's like calling removeEventListener. In fact, under the hood, as we'll see here, notice down here at the bottom, I'm creating the subscription object when you call forEach.

[00:05:16] And if you look at the definition of dispose, what does it do under the hood? It unhooks from the event handler, and that's how we assure that no more data is going to be sent. And so when we return an observable and somebody calls forEach and they pass in this observer object, remember the observer is just an object with the onNext, onError, and onCompleted methods.

[00:05:34] What's gonna happen is the observable, in order to deliver that information to you, it's gonna hook up an event handler to the DOM object. And whenever that handler function gets called, it's going to call the onNext method of the observer. So that's how it pushes the information along to the observer.

[00:05:52] Now every forEach method at the end has to return a subscription object. And so we create a subscription object, which is nothing but an object with a dispose method. And the contents of that dispose method are very simple. Whenever the consumer, whenever she calls dispose, whenever she says no more cake, please, I just have to make sure, as the producer, that I never give her another piece of cake.

[00:06:12] And how are we gonna do it here? I'm just gonna call and removeEventListener. And that's how you adapt the dom.addEventListener removeEventListener to an observable API.