Check out a free preview of the full A Tour of JavaScript & React Patterns course

The "Observer Pattern" Lesson is part of the full, A Tour of JavaScript & React Patterns course featured in this preview video. Here's what you'd learn in this lesson:

Lydia explains the observer pattern consists of an observable object and subscribers that will be notified by the observable object. This creates an efficient separation of concerns because the observable object has no knowledge of the subscribers. The subscribers are not aware of the underlying implementation that leads to the notification.


Transcript from the "Observer Pattern" Lesson

>> Let's move on to the observer pattern. It somehow always scrolls down to my StackBlitz whenever I open it. So with the observer pattern, if you've used React or just JavaScript in general, you may be familiar with something called observables. With the observer pattern, well, there are multiple parts at play here.

So we have the observable object, which can be observed by subscribers. And an observable object can in turn notify all those subscribers when an event occurs. So in this example, we have an observable there. It has a notify method, a subscribe method, and an unsubscribe method, just visualized, not in the code there.

So what we can do is we can subscribe certain functions, or any logic really, to that observable. And then when the notify method is invoked on this observable, all the subscribers that are currently subscribed to that observable get notified with that data. So for example, if we then notify subscribers on that observable, and we have four functions here that are all subscribers to this observable.

I'm just going make this big real quick. Whenever we notify it with certain data, so here the data is a string notify subscribers. All of these subscribers will get notified with that string, notify subscribers. And what they do with it, that's up to them, the observable doesn't care.

But they get passed that as their argument as data. So maybe we want to add some analytics here. Maybe we want to notify an observable whenever a user clicked on something. We'll actually do this in the challenge later on. But it's a very useful way to notify a lot of different parts of your application without having to repeat that code throughout the application.

It's not like, we have to send the request within every function. We can just all manage that within one observable, and they can then notify all the subscribers. It probably gets more clear in the challenge that we have later on. But yeah, so an observer object, we can just have a singleton like we had before.

And the easiest implementation is to have a notify method like we saw before, which gets some data. The data can just come from throughout the application. And then all the observers that are currently subscribed to this observable, we invoke that observer with the data. We don't know what these observers are.

We don't know what they do. The observable doesn't care. We just care about passing the data to all the observers that are currently subscribed. Then, of course, we have the subscribe method, which is just pushing that function to the observers array. So all the observers that care about this observable, I know I use these methods like observer, observable.

And then also we have unsubscribe to remove that function again from the observers list. So the easiest way, or a very simple example here, I guess, is say we have an observable and we have a button, so an element ID button, and we just wanna click it. We can just notify the observable with clicked, and say that we have a lot of subscribers, maybe Analytics subscribers, Google Analytics subscribers, email subscribers.

I don't know what all these functions do. They can be declared elsewhere in our code. They would all get notified with this string. And maybe they can also send events asynchronously based on that user event. So that's something that an observable can do. For example here, let me see if I can split the screen here.

We have this observer which is the exact same implementation that we had before. So we have notify, subscribe, and unsubscribe. Then we also just have a fake analytics page. So we have sendToGoogleAnalytics, sendToCustomAnalytics, and sendToEmail. And then here, I'm subscribing them. So now, whenever I invoke that subscribe method, these functions get pushed to the observer array.

Wait, I thought this was the observer, to this observers array. So then when you see when we notify, I think it might forget, this invokes that method. So it would in turn [LAUGH] see all this method. It would then pass this data here as this data. So now we see if we run, so in index.js, I just have this simple notify function.

And then that also have a notify just after a second just to kind of simulate maybe user events, I don't know. So when we run this, You can see that it automatically notified all the subscribers because we imported the analytics here. So it ran this file, it executed all these contents.

So it created the functions, and then also subscribe it to the observer. We then notified it here back in index.js with this string, which then sent the string from the observable, sorry, to all the observers. So it invokes these functions with this data. Yeah, so just look at the tradeoffs for the observer.

Yeah, so the observer object, like I said before, the function in this case, are not tightly coupled to the observable object. So the observable doesn't care about what the observers do. All it cares about is, okay, I'm going to pass this data to them. I don't care what they do with it.

Here's your data. So it can just be decoupled at any time. So maybe our application grows or it changes its need. Maybe we don't wanna have analytics anymore. We just easily unsubscribe. Yeah, so here, an example like the observable object is responsible for monitoring the events. And the observers simply handle the received data in whatever way possible.

Now, of course, make sure that if you're notifying all the subscribers, for example, and I know this is a micro optimization, but we like this for each method. If you have millions of observers, this might take a while. So just make sure that you're doing that in a performant way.

Maybe if it's asynchronous with Promise.all or something that it can run in parallel. Cuz in most cases, the observers, they don't rely on each other. They don't necessarily have to run sequentially. They're all just kinda standalone on their own. Okay, so I have a simple exercise here with the observer pattern.

So we have two buttons. So I have I'm a pink button and I'm a blue button. Now you can see that I've added an event listener here with a click. And it has some data, and it sends all these data to the Google Analytics, custom analytics, and send to email.

Same with the blue button, but, of course, the blue button sends different data. Now your exercise here is to change this so we aren't repeating ourselves. We are not explicitly invoking this function with the data. Instead, we will notify an observer that this click happened. And this observer will then notify this sendToGoogleAnalytics, sendToCustomAnalytics, and sendToEmail.

To achieve a similar result, we still want to log this data or we still wanna send it to Google Analytics, custom analytics whenever the user clicks. Just not in this way because we're repeating ourselves here. It's not very scalable, so we wanna use an observer instead.
>> So instead of repeating the functions, we notify the observer and the observer will take care of all those broadcasting.

>> Yes, so if you just need a sneak peek, it's pretty similar to what we did, or maybe not. Yeah, I guess it's pretty similar to what we did here with the analytics, and then subscribing them.
>> It kinda reminds me of event.
>> Yeah.
>> Cuz if you click a button, anything that's subscribed to the click listener will run.

>> That's using the observer pattern as well. It is really just a pattern. It's more like a way that you think about architecting your code about how the data is passed to certain parts of your code. So I would say that the events is also using that observer pattern.

Maybe not like one-on-one, and it doesn't have to be, but yeah, it's very similar.
>> Is the observer pattern and Pub/Sub pattern the same?
>> I believe so, I haven't used a Pub/Sub pattern in ages. So I don't know if it has other functionality that maybe makes it easier cuz the observer pattern is, of course, a very low level.

This is just a way to think about things. But I would say they're the same for what I know. Yeah, cuz it's like publish-subscribe, yeah.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now