JavaScript: Promise Patterns for scaleApp Applications

2015 Feb 14

I love scaleApp . It helps us modularize and divide an application in well-formed, isolated modules. It also provides a communication means between them all and sets a convenience infraestructure to put the pieces together. It is also easy to learn and to follow.

In all this time using it I ended writting a set of promise functions that help isolate some common issues of scaleApp in a recurring manner.

Module lifecycle

The following is the code for an empty module that responds to the initialize and destroy methods always as if it is an asynchronous module (see the done function):

var MyModule = function(sandbox){
	return {
		init: function(options, done){
			done();
		},
		destroy: function(done){
			done();
	  }
  };
};
core.register('myModule', MyModule);

So, the two firsts promise functions are in charge of start and stop a module:

var moduleStart = function(module, options) {
	return new Promise(function(resolve, error) {
		core.start(module, {
			options: options
		}, resolve );
	});
};

var moduleStop = function(module, options) {
  return new Promise(function(resolve, error) {
	  core.stop(module, resolve);
  });
};

Well, nothing outrageous. But it help us to start modules as promises with all of it’s advantages. For example: it is very easy to read and tweek the following code:

moduleStart('loader', options).then(function() {
  return moduleStop('loader', options);
}).then(function() {
  return Promise.all([
	  moduleStart('header')
	  moduleStart('main_layout')
	  moduleStart('footer')
  ]);
}).done(function() {
  return moduleStart('dashboard');
});

Module communication

Another common pattern is the communication between modules. When a module wants another to do something it sends a signal event to the performer module. Here again I force the system to work in an asynchronous manner so the receiver module should always signal a finished event even if all the work is done inside, for example, one method.

The promise that performs this functionality is the following:

var emitEvent = function(startEvent, endEvent, data) {
 return new Promise(function(resolve, reject) {
	 var subscription;
	 subscription = core.on(endEvent, function() {
		 subscription.detach();
		 resolve();
	 });
 	 core.emit(startEvent);
 });
};

I usually wrap all the events inside promise functions keeping the definition of the event names from spreading accross different parts of the application. 

For example the following are several helper functions that allows to send events from one module to another:

var headerShowSpinner = function(data) {
  return emitEvent('header.showSpinner', 'header.showSpinnerEnd', data);
};

var headerHideSpinner = function(data) {
  return emitEvent('header.hideSpinner', 'header.hideSpinnerEnd', data);
};

var mainLoadPanel = function(data) {
  return emitEvent('main.loadPanel', 'main.loadPanelEnd', data);
};

Once again this helps us writing code that is easier to tweek and understand. See how the module that invokes the following doesn’t need to know the name of the events but only the functionality:

headerShowSpinner().then(function() {
  return mainLoadPanel(options);
}).done(function() {
  headerHideSpinner();
});

These are just simple patterns. It is not rocket science. It just helped me and I hope it helps you.

javascript scaleapp promises
comments powered by Disqus