Software design patterns provide a means to communicate complex software concepts with a widely understood and agreed upon terminology. At their core, design patterns are a template for creating reusable solutions to commonly occurring software problems. They aren't as much a tool, yet a technique for problem solving what is commonplace to software development. In JavaScript, the Publish-Subscribe design pattern is significant in the architecture of many successful applications, and we will demonstrate how you can utilize it in your development.

Publish-Subscribe is frequently used in front-end code -- even developers who are not familiar with Publish-Subscribe by name will unknowingly use the pattern. This may look familiar.

// Javascript HTML DOM Event Example

document.getElementById('makeItHappenBtn').onclick = makeItHappen;

function makeItHappen() {
    document.getElementById('itsHappening').innerHTML = 'It is happening!';
}

// jQuery Event Handler Example

$('#makeItHappenBtn').on('click', function () {
  document.getElementById('itsHappening').innerHTML = 'It is happening!';
});

What we're stating in our code is on the click of the button run this function. We are subscribing to an event -- the click of the #makeItHappenBtn element -- and the DOM is handling the publish of the event (emitting the click event for our event handler to capture). Simple concept which nearly every JavaScript developer has likely used at one time or another for various purposes.

A key benefit of the Publish-Subscribe pattern is the establishment of single sources of responsibility. It facilitates the creation of an architecture that is easier for developers to maintain and reason about the intentions of the code. For a more elaborate scenario of utilizing the Publish-Subscribe pattern, I've added a large section of code below, so you can see how the Publish-Subscribe pattern may be used for practical purposes.

The example demonstrates how to integrate the design pattern when creating a Tracking component for handling various user events -- in this case a form submission. The Publish-Subscribe technique allows for the tracking code to be abstracted out of the Form class and into its own class handler. The Tracking class subscribes to key events, and the Form class is the example source for publishing an event the Tracking class is concerned about (the user form submission).

Note: the code examples follow a RequireJS code structure for clarity of file dependencies

PubSub.js

/* PubSub.js abstracts the implementation for the publish, subscribe, and unsubscribe pattern methods. */

/* Utilizes jQuery for method implementation but the rest of the code is not dependent on the implementation. So, it may be changed at any time without fear of application-level impact. */

/* To that end, the implementation details of each method can be changed to suit your needs (i.e. pure JavaScript, jQuery, Angular, etc) without needing to make global changes. */

define([
  'jquery'
], function ($) {
  'use strict';

  /**
  * Publish-Subscribe Pattern Implementation
  */

  var
    PubSub = {},
    obj = $({});

  PubSub.publish = function () {
    obj.trigger.apply(obj, arguments);
  };

  PubSub.subscribe = function () {
    obj.on.apply(obj, arguments);
  };

  PubSub.unsubscribe = function () {
    obj.off.apply(obj, arguments);
  };

  return PubSub;
});

EventHub.js

/* EventHub.js is the single storage hub for event notification definitions */

define([
], function () {
  'use strict';

  var EventHub = {};

  EventHub.FormSubmit = 'formSubmitEvent';

  return EventHub;
});

Form.js

/* Form.js is a generic class to publish an event on the form element submission */

define([
  'js/utils/EventHub',
  'js/utils/PubSub'
], function (EventHub, PubSub) {
  'use strict';

  /* Form class ... */

  var Form = {};

  /* insert logic to call onSubmit on form element submission */

  Form.onSubmit = function () {
    PubSub.publish(EventHub.FormSubmit, arguments);
  }

  return Form;
});

Tracking.js

/* Tracking.js is a generic class to subscribe to events for tracking */

define([
  'js/utils/EventHub',
  'js/utils/PubSub'
], function (EventHub, PubSub) {
  'use strict';

  /* Tracking class ... */

  var Tracking = {};

  /* insert logic to call subscriptions for tracking events */

  Tracking.subscriptions = function () {
    PubSub.subscribe(EventHub.FormSubmit, function (ev, args) {
        Tracking.onFormSubmit(ev, args);
      });
    }
  };

  Tracking.onFormSubmit = function () {
    // insert logic for tracking FormSubmit event

    // if desired, unsubscribe from the event so the event subscription will be removed
    PubSub.unsubscribe(EventHub.FormSubmit, arguments);
  };

  return Tracking;
});

Mark Curphey, Vice President, Strategy Mark Curphey is the Vice President of Strategy at CA Veracode. Mark is the founder and CEO of SourceClear, a software composition analysis solution designed for DevSecOps, which was acquired by CA Technologies in 2018. In 2001, he founded the Open Web Application Security Project (OWASP), a non-profit organization known for its Top 10 list of Most Critical Web Application Security Risks. Mark moved to the U.S. in 2000 to join Internet Security Systems (acquired by IBM), and later held roles including director of information security at Charles Schwab, vice president of professional services at Foundstone (acquired by McAfee), and principal group program manager, developer division, at Microsoft. Born in the UK, Mark received his B.Eng, Mechanical Engineering from the University of Brighton, and his Masters in Information Security from Royal Holloway, University of London. In his spare time, he enjoys traveling, and cycling.

Love to learn about Application Security?

Get all the latest news, tips and articles delivered right to your inbox.

 

 

 

contact menu