JavaScript Design Patterns: Observer

It’s time to introduce you guys to the Observer pattern. If you’ve been following this blog lately, you may have already had an introduction through my post talking about my jQuery plugin called JZ Publish/Subscribe. Well, here we’ll be talking about a few other ways to implement the Observer pattern, so you’ll know the method that works best for you and your application.

Observer Structure

Before we get started I’d like to point you to the fact that this post is part of a series of posts about JavaScript Design Patterns. If you’d like to read any of the other posts in this series you can find the list of them at the bottom of this post. It would probably be beneficial for any programmer that isn’t already well versed in JavaScript design patterns to go through these.

What is the Observer Pattern

The Observer pattern is a pretty simple concept. An observer (aka subscriber) subscribes to an observable object (aka publisher), waiting for something of interest to happen. Observers are also able to unsubscribe from the observer. At this point the behavior is dependent upon the way you have implemented the pattern. There are two basic methods for observers to get information on what is going on: push and pull. In the push method, whenever something happens, the observable immediately notifies the observers of the event. In the pull method, the observer will check with the observable to see if anything has changed whenever the observer feels it necessary to check.

I’m betting you want to see an example. Of course you do! You’re a programmer and to you code makes more sense than plain English, right? Let’s start off with an example of the push method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
var Observable = function() {
this.subscribers = [];
}

Observable.prototype = {
subscribe: function(callback) {
// In most situations, you would check to see if the
// callback already exists within the subscribers array,
// but for the sake of keeping us on track and because
// this isn't necessarily included, we'll leave it out.
// Just add the callback to the subscribers list
this.subscribers.push(callback);
},
unsubscribe: function(callback) {
var i = 0,
len = this.subscribers.length;

// Iterate through the array and if the callback is
// found, remove it.
for (; i < len; i++) {
if (this.subscribers[i] === callback) {
this.subscribers.splice(i, 1);
// Once we've found it, we don't need to
// continue, so just return.
return;
}
}
},
publish: function(data) {
var i = 0,
len = this.subscribers.length;

// Iterate over the subscribers array and call each of
// the callback functions.
for (; i < len; i++) {
this.subscribers[i](data);
}
}
};

var Observer = function (data) {
console.log(data);
}

// Here's where it gets used.
observable = new Observable();
observable.subscribe(Observer);
observable.publish('We published!');

There are a few things to talk about here. First off, all the functions related to the observer pattern are implemented within Observable. With JavaScript’s flexibility, you could also make the observer able to do the subscribing and unsubscribing, but I believe that it’s more sensible and understandable to implement all of that within the observable object. Another noteworthy point is that the observer is simply a function that can be used as a callback. In languages like Java, an observer would be an object that implements a specified interface. Then the entire object would be subscribed and the observable would simply call the method specified by the observer interface. Finally, in this example Observable is class that can be used by itself, though it is far more useful to be inherited by other objects so that they can become observable.

Now we’ll implement the pull method of the observer pattern. When you’re using the pull method, it makes more sense to swap things around a bit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Observable = function() {
this.status = "constructed";
}
Observable.prototype.getStatus = function() {
return this.status;
}

Observer = function() {
this.subscriptions = [];
}
Observer.prototype = {
subscribeTo: function(observable) {
this.subscriptions.push(observable);
},
unsubscribeFrom: function(observable) {
var i = 0,
len = this.subscriptions.length;

// Iterate through the array and if the observable is
// found, remove it.
for (; i < len; i++) {
if (this.subscriptions[i] === observable) {
this.subscriptions.splice(i, 1);
// Once we've found it and removed it, we
// don't need to continue, so just return.
return;
}
}
}
doSomethingIfOk: function() {
var i = 0;
len = this.subscriptions.length;

// Iterate through the subscriptions and determine
// whether the status has changed to ok on each of them,
// and do something for each subscription that has
for (; i < len; i++) {
if (this.subscriptions[i].getStatus() === "ok") {
// Do something because the status of the
// observable is what we want it to be
}
}
}
}

var observer = new Observer(),
observable = new Observable();
observer.subscribeTo(observable);

// Nothing will happen because the status hasn't changed
observer.doSomethingIfOk();

// Change the status to "ok" so now something will happen
observable.status = "ok";
observer.doSomethingIfOk();

This is quite different from the push way of doing things, isn’t it? Now, whenever the observer feels like it should – or in this case, whenever I tell it to – it will check on the status of the observable(s) it is subscribed to. Normally this would be on a timer or something, but I decided to keep it simple and just call it manually. Once again Observable in this code shouldn’t technically be used by itself. Instead it should be subclassed so that there are built in mechanisms that change the status, rather than manually changing it like I did in the example.

The Observer Patterns You’ve Already Seen

The examples I’ve given are very simple examples and generally an observable object can have more than one type of event to be observed. Speaking of events, you may or may not have realized that event handling on DOM elements is an implementation of the observer pattern. The observer pattern is everywhere and is quite powerful and useful. Also, many jQuery plugins that use animations will include the observer pattern so you can inject your own functionality into different points of an animation.

I Observe That The End Is Near

The observer pattern is a marvelous tool for maintaining and organizing large action-based applications or even just to make your jQuery plugin more accessible and flexible. It adds a nice level of abstraction to help decouple your code and keep it clean and maintainable. Obviously the observer pattern shouldn’t be used for everything, but it can be quite useful in innumerable situations.

If you haven’t seen it yet, you should check out JZ Publish/Subscribe to see another way the observer pattern can be implemented. You can even see how and why you should use it. If you’d rather move on from the observer pattern, you can check out the rest of the posts in the JavaScript Design Patterns series in the list below. Otherwise, I’d be delighted if you’d share this post with your friends or leave me a comment below. In any case, Happy Coding!

JavaScript Design Patterns series:

Author: Joe Zimmerman

Author: Joe Zimmerman Joe Zimmerman has been doing web development ever since he found an HTML book on his dad's shelf when he was 12. Since then, JavaScript has grown in popularity and he has become passionate about it. He also loves to teach others though his blog and other popular blogs. When he's not writing code, he's spending time with his wife and children and leading them in God's Word.