Skip to content

Instantly share code, notes, and snippets.

@hns
Created April 22, 2010 20:51
Show Gist options
  • Save hns/375799 to your computer and use it in GitHub Desktop.
Save hns/375799 to your computer and use it in GitHub Desktop.
Implementation of free-threaded promises in Rhino
var {setTimeout} = require("ringo/scheduler");
export("defer");
var NEW = 0;
var FULFILLED = 1;
var FAILED = 2;
/**
* Returns a promise and a function to resolve it.
* @example
* exports.asyncAction = function(request) {
* var response = defer();
* setTimeout(function() {
* response.resolve({
* status: 200, headers: {}, body: ["Delayed"]
* });
* }, 1000);
* return response.promise;
* }
*/
function defer() {
var value;
var listeners = [];
var state = NEW;
var lock = new java.lang.Object();
var resolve = sync(function(result, isError) {
if (state !== NEW) {
throw new Error("Promise has already been resolved.");
}
value = result;
state = isError ? FAILED : FULFILLED;
listeners.forEach(notify);
listeners = [];
lock.notifyAll();
}, lock);
var notify = function(listener) {
var isError = state === FAILED;
var callback = isError ? listener.errback : listener.callback;
setTimeout(function() {
if (!callback) {
// if no callback defined we pass through the value
listener.tail.resolve(value, isError);
} else {
try {
listener.tail.resolve(callback(value), isError);
} catch (error) {
listener.tail.resolve(error, true);
}
}
}, 0);
};
var promise = {
then: sync(function(callback, errback) {
if (typeof callback !== "function") {
throw new Error("First argument to then() must be a function.");
}
var tail = defer();
var listener = {
tail: tail,
callback: callback,
errback: errback
};
if (state === NEW) {
listeners.push(listener);
} else {
notify(listener);
}
return tail.promise;
}, lock),
wait: sync(function() {
if (state === NEW) {
lock.wait();
}
if (state === FAILED) {
throw value;
} else {
return value;
}
}, lock)
};
return {
resolve: resolve,
promise: promise
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment