@emartech/faye-redis-sharded
Version:
Redis backend engine for Faye with support for sharding
148 lines (115 loc) • 3.71 kB
JavaScript
(function() {
;
var timeout = setTimeout;
var defer;
if (typeof setImmediate === 'function')
defer = function(fn) { setImmediate(fn) };
else if (typeof process === 'object' && process.nextTick)
defer = function(fn) { process.nextTick(fn) };
else
defer = function(fn) { timeout(fn, 0) };
var PENDING = 0,
FULFILLED = 1,
REJECTED = 2;
var RETURN = function(x) { return x },
THROW = function(x) { throw x };
var Promise = function(task) {
this._state = PENDING;
this._callbacks = [];
this._errbacks = [];
if (typeof task !== 'function') return;
var self = this;
task(function(value) { fulfill(self, value) },
function(reason) { reject(self, reason) });
};
Promise.prototype.then = function(callback, errback) {
var next = {}, self = this;
next.promise = new Promise(function(fulfill, reject) {
next.fulfill = fulfill;
next.reject = reject;
registerCallback(self, callback, next);
registerErrback(self, errback, next);
});
return next.promise;
};
var registerCallback = function(promise, callback, next) {
if (typeof callback !== 'function') callback = RETURN;
var handler = function(value) { invoke(callback, value, next) };
if (promise._state === PENDING) {
promise._callbacks.push(handler);
} else if (promise._state === FULFILLED) {
handler(promise._value);
}
};
var registerErrback = function(promise, errback, next) {
if (typeof errback !== 'function') errback = THROW;
var handler = function(reason) { invoke(errback, reason, next) };
if (promise._state === PENDING) {
promise._errbacks.push(handler);
} else if (promise._state === REJECTED) {
handler(promise._reason);
}
};
var invoke = function(fn, value, next) {
defer(function() { _invoke(fn, value, next) });
};
var _invoke = function(fn, value, next) {
var called = false, outcome, type, then;
try {
outcome = fn(value);
type = typeof outcome;
then = outcome !== null && (type === 'function' || type === 'object') && outcome.then;
if (outcome === next.promise)
return next.reject(new TypeError('Recursive promise chain detected'));
if (typeof then !== 'function') return next.fulfill(outcome);
then.call(outcome, function(v) {
if (called) return;
called = true;
_invoke(RETURN, v, next);
}, function(r) {
if (called) return;
called = true;
next.reject(r);
});
} catch (error) {
if (called) return;
called = true;
next.reject(error);
}
};
var fulfill = Promise.fulfill = Promise.resolve = function(promise, value) {
if (promise._state !== PENDING) return;
promise._state = FULFILLED;
promise._value = value;
promise._errbacks = [];
var callbacks = promise._callbacks, cb;
while (cb = callbacks.shift()) cb(value);
};
var reject = Promise.reject = function(promise, reason) {
if (promise._state !== PENDING) return;
promise._state = REJECTED;
promise._reason = reason;
promise._callbacks = [];
var errbacks = promise._errbacks, eb;
while (eb = errbacks.shift()) eb(reason);
};
Promise.defer = defer;
Promise.deferred = Promise.pending = function() {
var tuple = {};
tuple.promise = new Promise(function(fulfill, reject) {
tuple.fulfill = tuple.resolve = fulfill;
tuple.reject = reject;
});
return tuple;
};
Promise.fulfilled = Promise.resolved = function(value) {
return new Promise(function(fulfill, reject) { fulfill(value) });
};
Promise.rejected = function(reason) {
return new Promise(function(fulfill, reject) { reject(reason) });
};
if (typeof Faye === 'undefined')
module.exports = Promise;
else
Faye.Promise = Promise;
})();