Transcript from the "Task #4 - Event Emitters" Lesson
>> Kyle Simpson: Just for the sake of keeping going along the same lines of thinking that we had before. I'm gonna skip items one and two in the task 4. I'll come back in the very end and do those quickly those are kinda some throwaway things for me to try but 3 and 4 are really spot on to what we were just talking about.
[00:00:22] So I already showed you that we could refactor to add an API method which was this load person method to our API and then we could directly call it from inside of the carousel function. Okay? There's a couple of problems with that when you start thinking of an even bigger level at an even higher level of abstraction.
[00:00:45] So we certainly improve things by doing that compared to what we had before. But even this may not be the end goal or the best possible design. So this next line of thinking is an even further stretch of your envelope. Conceptually speaking, okay? One of the things that we've done here is that even though we have the two actual pieces of logic separate.
[00:01:08] We've created a very strong tie between these two modules. And we only have one of them, so it doesn't seem like such a big deal. But if the carousel module had 15 different functions in it, and it was calling five or ten public API methods on the details module, and if the details module was calling the carousel module in a bunch of different ways.
[00:01:32] There's an awful lot of spaghetti mixture that would be happening between the two. That design is certainly functional and that's what most people think constitutes proper software design. My feeling is it's functional but it's not ideal. I don't like those strong brittle ties with things. The carousel module should to the extent possible be completely independent from the details module.
[00:02:01] It should know as little as possible about the details module. In fact, it'd be good if it didn't know about it all. That seems like an anachronism. It seems like It's impossible for the carousel module to call the details module or to invoke some of it's behavior and simultaneously not know about the module at all.
[00:03:05] And they don't know about each other but they do need to cooperate to get the job done. Could I create a layer of indirection between them with an event system such that this guy over here could send out an event, doesn't care who captures the event. And this guy over here could listen for the event, doesn't care who sent it.
[00:03:26] Do you see how that would create this sort of triangular layer of indirection. Where they don't have to know about each other but they still are able to talk through this intermediary. And what I've just described this idea of sending out an event, aka publishing an event. And listening for an event.
[00:03:41] Aka subscribing to an event. If you've been around at all in the development industry and web industry for a little while you may have heard few years back, pub sub was a big hot buzzword that was going around. And people were creating companies for pub subbing and frameworks and all kinds of crazy things and they were books written about it.
[00:04:00] And all of that nonsense boils down to do I have an object that can listen for events and send events? You can take all of that nonsense that was going on for two or three years and boil it down to a centralized object that can emit events and listen for events.
[00:04:23] So I could create one of those really easily. If I could do that I could create a layer of indirection between all of my modules so that they didn't have to know about each other. And that's what we're gonna get out. That's kind of the final thing that we wanna spend our time looking at.
[00:04:35] So I have provided to you, I've included to you a file called event emitter two dot JS. We're not loading it yet but we're gonna load it now. So I'm gonna add it to my list. So script source js/eventemitter2.
>> Kyle Simpson: It's one of those cans where the label tells you exactly what it's doing on the inside of the box.
[00:05:03] That thing creates something that lets us make event emitters. It's a tiny little library like really tiny. But the great part about it is, it is the exact same API as how events work in the node world on the server. It literally took the event emitter API. They added some extra stuff to it but they took the event emitter API and they ported it so they could be used in the browser as well.
[00:05:28] And when we talk tomorrow afternoon if any of you come tomorrow afternoon. We talk about kind of the final arc of all this discussion. We talk about sharing code between things that holy grail of sharing code is when I don't even have to switch I can just use the exact same code in both places.
[00:05:42] So what's nice about event emitters is I can write the same code, and it'll run identically no matter what the environment. For our purposes, it's just a tiny library that lets us do pub sub without any need for a crazy framework, or service, or an app, or book.
[00:05:58] We don't need any of that, we need an object that we can send events to and listen to events. So here's how we use eventemitter, let's go back to our app.js, and let's make an event object. I'll put it on the window so that it's going to be available to everybody, so this is a global variable that everybody can access.
[00:06:22] I'll call it EVT, that's my normal style of how I do it. So I'll call it EVT. And it needs to be an event emitter. So I'm just gonna say new EventEmitter2 cuz the event emitter is the constructor for this kind of object. We haven't dealt with what new does just don't worry about that detail.
[00:06:41] It's constructing something. So that thing is a thing that I can use in multiple places now. So let's go back to the code where I am calling .loadPerson. If I could think about that in terms of not telling you exactly what I want to do but describing abstractly or indirectly what I hope would happen.
[00:07:06] I would, instead of calling this a loadPerson, I would call this event that has happened person selected.
>> Kyle Simpson: Cuz I don't care what happens when a person gets selected from the abstract perspective, from the conceptual perspective. I don't care what you do with it, I just wanna let you know that a person has been selected.
[00:07:27] So if I did, EVT.emit which is how you send events. And I used, I just make up an event name like person-selected. And I need to give it some data. The only piece of data that I need to pass along is the ID. So we've taken one line and replaced it with that other line.
[00:07:51] I'm now sending out an event called person-selected and I do not care who if anyone listens to the event. It's completely, I don't even know that there is somebody that cares about the event. But I just wanna let people know just in case anybody wanted and in case anybody care.
[00:08:07] Here is an important detail what if there was more than one different part of the application that cared. That's totally cool with me. I don't care. If there were 15 different parts of the application that each had a special different job to do once a person was selected.
[00:08:21] That's cool with me. Cuz I just send out the event to the hub and I let the other people deal with it. Okay. It's an extra layer of indirection here. Now, how do I use that on the details side? Well, I come to the details module. And, I need to listen for that event.
[00:08:39] A good thing to do in my init function, I'm going to listen. EVT.on is how we listen. For the person-selected event. And, I need to have it call a function. Anybody have any guess as to what function I want it to call?
>> Speaker 2: Load person.
>> Kyle Simpson: Load person.
[00:08:56] That's cool right? I don't even need to make a new function I'll just call it loadPerson. It's nice and convenient that it happens to be passing along the data to me that I'm going to receive from that event. Do you see how easy that was to actually create a full layer of abstraction or indirection between the two?
[00:09:13] Now neither one of the two knows about the other one. They don't need to. And because I've done that, I've made my code significantly more flexible. You know what my favorite trick is when I deal with stuff like events? Now I can independently test these two modules. I can create a test mock that creates a fake event called person selected.
[00:09:37] Doesn't wait for somebody to click a button I just make a person event. And I throw out a piece of data and I test whether or not the details module receives that event and does what it needs to.
>> Kyle Simpson: Because I have that layer of indirection, I don't have to manually call a thing.
[00:09:53] I can just throw out events. Or I can test the carousel module by setting up a listener to see if that event gets fired. And see if the carousel does his job.
>> Kyle Simpson: So events create that abstraction which lets me have a lot more flexibility. A lot less rigidity to my design, more flexible for testing and so forth.
[00:10:13] I'm a huge fan of this approach to software design. I don't like having one module calling another. Wherever possible, if I can avoid it, I try to avoid that, it's not always possible. But were possible if I can avoid it, if it's just like a throwing a thing over the fence sort of an action and I don't really need a response back.
[00:10:32] I just publish an event.