Skip to content

Instantly share code, notes, and snippets.

@fictorial
Created December 1, 2009 04:40
Show Gist options
  • Save fictorial/246060 to your computer and use it in GitHub Desktop.
Save fictorial/246060 to your computer and use it in GitHub Desktop.
/**
* A PromiseChain calls multiple functions in the same order added, and
* expects each function to return a Promise. The next function or link in
* the chain is invoked only when the previous promise emits success. The next
* function is passed the result of the previous function emits on success.
*
* A PromiseChain itself has a Promise to track overall success/failure of the
* chain. If all functions in the chain emit success, the chain's Promise emits
* success in turn, passing the value emitted by the last link/function of the
* chain.
*
* The first link/function to emit error causes the chain to immediately emit error;
* and the evaluation of the chain stops immediately.
*/
function PromiseChain() {
this.functions = [];
this.promise = new process.Promise();
};
exports.PromiseChain = PromiseChain;
require("sys").inherits(PromiseChain, process.EventEmitter);
/**
* Adds a function to the end of the chain.
* @param a_function The function to call.
* @param this_arg The object object on which to call the function (optional).
* @return the length of the chain after adding 'a_function'.
*/
PromiseChain.prototype.push = function (a_function, this_arg) {
if (typeof(a_function) !== 'function')
throw new Error("not a function");
this.functions.push({ object: this_arg, method: a_function });
return this.functions.length;
};
/**
* Evaluate the links of the chain.
* @param * Whatever is passed to this method is passed to the first link.
*/
PromiseChain.prototype.run = function () {
var self = this;
var on_error = function (msg) {
self.promise.emitError(msg || "link in chain emitted error");
};
try {
var entry = this.functions.shift();
var link_promise = entry.method.apply(entry.object, arguments);
link_promise.addCallback(function () {
var results = Array.prototype.slice.call(arguments);
if (self.functions.length === 0) {
self.promise.emitSuccess(results);
self.promise = null;
} else {
self.run(results);
}
});
link_promise.addErrback(on_error);
} catch (e) {
on_error(e);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment