will
Version:
Flexible futures
261 lines (227 loc) • 7.29 kB
JavaScript
// Generated by CoffeeScript 1.6.3
(function() {
var Acceptance, Deferral, Future, Rejection, isArray, isError, slice;
isError = require('util').isError;
isArray = require('omicron').isArray;
slice = Array.prototype.slice;
Deferral = null;
Acceptance = null;
Rejection = null;
module.exports = Future = (function() {
var NULL_CONTEXT, join, later,
_this = this;
function Future() {}
NULL_CONTEXT = (function() {
return this;
})();
Future.later = later = (typeof process !== "undefined" && process !== null) && ("" + process) === '[object process]' ? function(callback, args) {
var _this = this;
if ((args != null) && !isArray(args)) {
args = [args];
}
process.nextTick(function() {
return callback.apply(_this, args);
});
} : function(callback, args) {
var _this = this;
if ((args != null) && !isArray(args)) {
args = [args];
}
setTimeout((function() {
return callback.apply(_this, args);
}), 1);
};
Future.transform = function(fn, infallible) {
if (infallible == null) {
infallible = false;
}
return function() {
var args, deferral;
deferral = new Deferral;
args = slice.call(arguments);
args.push(function(error) {
if (infallible) {
return deferral.accept.apply(deferral, arguments);
}
if (error == null) {
return deferral.accept.apply(deferral, slice.call(arguments, 1));
} else {
return deferral.reject(error);
}
});
fn.apply(this, args);
return deferral.promise();
};
};
Future.isFuturoid = function(value) {
if (!value) {
return null;
}
if (value instanceof Future || (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function') {
return value;
}
return null;
};
Future.resembles = Future.resemblesFuture = Future.isFuturoid;
Future.getThenFrom = function(thenable) {
var method;
if ((thenable != null) && (typeof thenable === 'object' || typeof thenable === 'function')) {
if (typeof (method = thenable.then) === 'function') {
return method;
}
}
};
Future.resolve = function(value) {
if ((isError(value)) || (isArray(value)) && isError(value[0])) {
return Future.reject(value);
} else {
return Future.accept(value);
}
};
Future.of = Future.wrap = Future.resolve;
Future.accept = function(value) {
return new Acceptance(value);
};
Future.reject = function(value) {
return new Rejection(value);
};
Future.willBe = function(value) {
var deferral;
deferral = new Deferral;
later((isError(value)) || (isArray(value)) && isError(value[0]) ? function() {
return deferral.reject(value);
} : function() {
return deferral.accept(value);
});
return deferral.promise();
};
Future.join = join = function(futures, limit, positive) {
var contingency, count, deferral, expectation, future, index, isFuturoid, length, method, onAccepted, onRejected, order, resolve, results, _i, _len;
if (positive == null) {
positive = true;
}
if ((length = futures != null ? futures.length : void 0) == null) {
throw TypeError;
}
if (limit == null) {
limit = length;
}
if (!((0 <= limit && limit <= length))) {
throw RangeError;
}
if (length === 0 || limit === 0) {
return (positive ? Rejection : Acceptance).promise();
}
isFuturoid = Future.isFuturoid, resolve = Future.resolve;
count = 0;
results = Array(length);
order = [];
deferral = new Deferral;
for (index = _i = 0, _len = futures.length; _i < _len; index = ++_i) {
future = futures[index];
if (typeof future === 'function') {
future = future();
}
if (!isFuturoid(future)) {
future = resolve(future);
}
expectation = (function(index) {
return function(payload) {
results[index] = payload;
order.push(index);
if (++count >= limit) {
return deferral.accept(results, order, payload, index);
}
};
})(index);
contingency = (function(index) {
return function(payload) {
results[index] = payload;
order.push(index);
if (--length < limit) {
return deferral.reject(results, order, payload, index);
}
};
})(index);
if (positive) {
onAccepted = expectation;
onRejected = contingency;
} else {
onAccepted = contingency;
onRejected = expectation;
}
method = future instanceof Future ? 'bind' : 'then';
future[method](onAccepted, onRejected);
}
return deferral.promise();
};
Future.all = function(futures) {
return join(futures);
};
Future.none = function(futures) {
return join(futures, null, false);
};
Future.any = function(limit, futures) {
if (futures === void 0) {
futures = limit;
limit = 1;
}
return join(futures, limit);
};
Future.notAny = function(limit, futures) {
if (futures === void 0) {
futures = limit;
limit = 1;
}
return join(futures, limit, false);
};
Future.prototype.bind = function(onAccepted, onRejected) {
if (typeof onAccepted === 'function') {
this.once('accepted', function() {
try {
return onAccepted.apply(NULL_CONTEXT, arguments);
} catch (_error) {}
});
}
if (typeof onRejected === 'function') {
this.once('rejected', function() {
try {
return onRejected.apply(NULL_CONTEXT, arguments);
} catch (_error) {}
});
}
};
Future.prototype.done = Future.prototype.bind;
Future.prototype.then = function(onAccepted, onRejected) {
var successor;
successor = new Deferral;
this.once('accepted', typeof onAccepted === 'function' ? function() {
var error;
try {
return successor.resolve(onAccepted.apply(NULL_CONTEXT, arguments));
} catch (_error) {
error = _error;
return successor.reject(error);
}
} : function() {
return successor.accept.apply(successor, arguments);
});
this.once('rejected', typeof onRejected === 'function' ? function() {
var error;
try {
return successor.resolve(onRejected.apply(NULL_CONTEXT, arguments));
} catch (_error) {
error = _error;
return successor.reject(error);
}
} : function() {
return successor.reject.apply(successor, arguments);
});
return successor.promise();
};
return Future;
}).call(this);
Deferral = require('./deferral');
Acceptance = require('./acceptance');
Rejection = require('./rejection');
}).call(this);