Skip to content

Instantly share code, notes, and snippets.

@bjoerge
Created January 8, 2012 15:52
Show Gist options
  • Save bjoerge/1578785 to your computer and use it in GitHub Desktop.
Save bjoerge/1578785 to your computer and use it in GitHub Desktop.
Another minimal, but more feature rich Promise implementation
var Promise = (function() {
var api_tuples = {notify: 'progress', resolve: 'then', reject: 'fail', done: 'always' }, // all (action, callback_adder)-tuples)
isFunction = function(obj) {
return Object.prototype.toString.call(obj) == '[object Function]';
},
slice = Array.prototype.slice,
each_pair = function(obj, callback) {
Object.keys(obj).forEach(function(key) { callback(key, obj[key]); });
},
invokeEach = function(funcs) {
for (var i = 0, len = funcs.length; i < len; i++) {
funcs[i].apply(null, slice.call(arguments, 1));
}
},
return_false = function() { return false; },
return_true = function() { return true; };
return function() {
var self = {isResolved: return_false, isRejected: return_false},
callbacks = {},
fullfill = function(type, value) {
self.resolve = self.reject = function() { throw new Error('Promise already completed'); };
self[api_tuples[type]] = function(callback) { callback(value); }; // Switch to synchronized
invokeEach(callbacks[type], value);
self[type === 'resolve' ? 'isResolved' : 'isRejected'] = return_true;
invokeEach(callbacks.done, value);
callbacks = null;
};
each_pair(api_tuples, function(action, callback_adder) {
var _callbacks = callbacks[action] = [];
self[callback_adder] = function(callback) {
if (!isFunction(callback)) { throw new Error("Callback for "+callback_adder+" must be a function."); }
_callbacks.push(callback);
};
if (action === 'done') { return; } // done is internal, do not expose
self[action] = (action === 'notify') ?
function(value) { invokeEach(_callbacks, value); } : function(value) { fullfill(action, value); };
});
return self;
};
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment