By Alvie Amar | 3/6/2017 | General |Beginners

The Observer Pattern in Javascript

The Observer Pattern in Javascript

There are things in your programs that will changes from time to time. From displaying a new type of view or updating a section of your content, the Observer pattern is commonly associated with these type of functions. The observer pattern incorporates this by updating views whenever an object is modified.

One good example of this is AngularJS $scope object updates an event that can be triggered by another component.

 

// Controller 1
$scope.$on('titleChange', function(event, args)
{
   $scope.title = args.title;
});

// Controller 2
$scope.pageTitleChange = function(title)
{
   $scope.$emit('titleChange', {title: title});
};

With the use of the Observer pattern it is very important that we are able to identify and pinpoint the subject. In AngularJS, we have prebuilt observers with the use of watchers. Which basically “watches” variables, functions and objects.

 

The Observer Pattern is also known as the Publish-Subscribe pattern in which it defines a one-to-many relationship between other objects and changes it states. Objects that have a one-to-many relationship with other objects are either called the subject or the publisher. The subject can have x number of dependent observers, in which it notifies the x number of observers it can subscribe to in receiving notifications. This is important if you are planning to build web apps that you end up writing with many event handlers. These event handlers are functions and will be notified when a certain event triggers.

 

First of all let’s define the Observer pattern. It will always have a subject. A subject must know its observers and provides an interface in attaching or detaching observer objects.

 

The next one is the observer, it defines the updating of objects whenever a Subject is notified.

 

Let’s start with a simple example.

 

The Count function will hold the current count and give as a function that will increment in count.

 

// Observer
function Count() {
 this.count = 0;
}
// Counter for increment
Count.prototype.increment = function (amount) {
 this.count += amount || 1;
};

So how do we communicate to other parts of our application? This is where the observers come in.  Let’s change the Count to an observable object and a collection of observers to give the Count to be notified whenever there is a change happening. Let us modify the code a bit.

 

 

// Observe
function Count() {
 this.count = 0;
 this.observers = [];
}

// Counter for increment
Count.prototype.increment = function (amount) {
 this.count += amount || 1;
 this.notify({ count: this.count });
};

// Adding the observer
Count.prototype.addObserver = function (observer) {
 this.observers.push(observer);
};

// Notifying the observer
Count.prototype.notify = function (data) {
 this.observers.forEach(function (observer) {
   observer.call(null, data);  
 });
};

The next thing we need to do is to make the Count as the observable.

 

// Create a new instance of count
var counter = new Count();

// Add an observer to the instance.
counter.addObserver(function () {
 console.log(counter.count);
});

// Do something in the application that would call increment.
// When a button is clicked, it will notify and call all observers
$("#btnVisitorCounter").on("click", function () {
 counter.increment();
});

From the added code above, whenever the user clicks the btnVistitorCounter button, counter increment will notify all observers. In this case, it will continuously be added.

 

In this example we try to create an Observer pattern with the loginHandler as the Observer. The handler will check the login and logout events when a button is clicked in a system. The eventListener accepts two parameters in which the first one is the event, while the second one is the context. We also added a Log helper function that logs all events and displays the data.

 

function Button() {
// observers
   this.handlers = [];  
}
// Button object
Button.prototype = {
   //Methods in the button object
   login: function(fn) {
// Handle complicated login logic
       this.handlers.push(fn);
   },
   logout: function(fn) {
// Handle complicated logout logic
       this.handlers.push(fn);
   },
// Event listener for the object
   eventListener: function(o, thisObj) {
       var scope = thisObj || window;
       this.handlers.forEach(function(item) {
           item.call(scope, o);
       });
   }
}
// Log Helper
var logEvent = (function() {
   var logEvent = "";
   return {
       add: function(message)
         {
           logEvent += message + "\n";
         },
       show: function()
         {
           console.log(logEvent);
           logEvent = "";
         }
   }
})();
//Run the program
function run() {
// Login Handler for events
   var loginHandler = function(item) {
       logEvent.add("Event: " + item);
   };
   var click = new Button();
   click.login(loginHandler);
   click.eventListener('Login User 1');
   click.logout(loginHandler);
   click.eventListener('Logout User 1');
   click.login(loginHandler);
   click.eventListener('Login User 3');
   click.login(loginHandler);
   click.eventListener('Login User 2');
   click.logout(loginHandler);
   click.eventListener('Logout User 2');
   click.logout(loginHandler);
   click.eventListener('Logout User 3');
   logEvent.show();
}

run();

The observer pattern does wonderful things in maintaining and keeping large event based applications, making your jQuery or any type of JavaScript framework you are using to be more accessible to use. It also adds a level of abstraction to keep your code clean and maintainable.

Interested in other JavaScript patterns? Read about the Singleton Pattern in JavaScript or

Visit our homepage to compare JavaScript Libraries

By Alvie Amar | 3/6/2017 | General

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
2340
Meir Rabinovich
Real time and embedded developer
Hardware and RT | General Libraries and 5 more
View Profile
User photo
1540
Nathan Gordon
Full Stack developer
Web | JavaScript and 1 more
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now