Created
December 1, 2009 04:40
-
-
Save fictorial/246060 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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