Skip to content

Instantly share code, notes, and snippets.

@briancavalier
Last active December 27, 2015 18:29
Show Gist options
  • Save briancavalier/7370665 to your computer and use it in GitHub Desktop.
Save briancavalier/7370665 to your computer and use it in GitHub Desktop.
"Promisify" a business object using an internal queue to serialize async operations
var when = require('when');
var delay = require('when/delay');
var slice = Array.prototype.slice;
var promisePrototype = Object.getPrototypeOf(when.resolve());
//---------------------------------------------------------
// A simple business object
//---------------------------------------------------------
function MyObj() {
this._queue = when.resolve();
this.value = 0;
}
//---------------------------------------------------------
// MyObj's prototype
// We'll promisify this and then set it as MyObj's prototype
// These methods are allowed to return promises
//---------------------------------------------------------
var methods = {
call1: function(x) {
// Implement call1 with whatever business logic you need
console.log('call1 business logic', x);
this.value += x;
return this.value;
},
call2: function(x) {
// Implement call2 with whatever business logic you need
console.log('call2 business logic', x);
this.value += x;
// For fun, return a delayed value
return delay(1000).yield(this.value);
},
call3: function(x) {
// Implement call3 with whatever business logic you need
console.log('call3 business logic', x);
this.value += x;
return this.value;
}
};
//---------------------------------------------------------
// Set MyObj's prototype by creating queueing versions of its
// methods, and then adding the promise API (then, otherwise, etc.)
// to provide access to the current queue value.
//---------------------------------------------------------
MyObj.prototype = mixinPromiseMethods(makeQueuedMethods(methods), promisePrototype);
//---------------------------------------------------------
// Here's how you can use it
//---------------------------------------------------------
var ob = new MyObj()
ob.call1(1)
.call2(2)
.call3(3)
.then( function(result) { console.log( result ); })
.otherwise( function(err) { console.log( err ); });
//---------------------------------------------------------
// Helpers for promisifying methods and adding promise API
//---------------------------------------------------------
// Promisify business logic methods
function makeQueuedMethods(methods) {
return Object.keys(methods).reduce(function (prototype, methodName) {
prototype[methodName] = function () {
var args = slice.call(arguments);
var self = this;
this._queue = when(this._queue, function () {
return methods[methodName].apply(self, args);
});
return this;
};
return prototype;
}, {});
}
// Add promise API, routing to internal queue
function mixinPromiseMethods(prototype, promisePrototype) {
return Object.keys(promisePrototype).reduce(function(prototype, methodName) {
prototype[methodName] = function() {
return this._queue[methodName].apply(this._queue, slice.call(arguments));
};
return prototype;
}, prototype);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment