UNPKG

forkjoin

Version:

Fork/Join primitives for async programming (experimental)

293 lines (275 loc) 7.25 kB
// Generated by CoffeeScript 1.9.1 (function() { var async, collect, createTask, forEach, fork, forkjoin, head, isFunction, isFuture, join, lift, map, resolve, seq, slice = [].slice; isFunction = function(f) { return 'function' === typeof f; }; isFuture = function(a) { if (a != null ? a.isFuture : void 0) { return true; } else { return false; } }; head = function(a) { if (a) { return a[0]; } else { return void 0; } }; async = function(f) { return function() { var args, error, go, j; args = 2 <= arguments.length ? slice.call(arguments, 0, j = arguments.length - 1) : (j = 0, []), go = arguments[j++]; try { return go(null, f.apply(null, args)); } catch (_error) { error = _error; return go(error); } }; }; fork = function(continuable, args) { var _continuations, link, propagate, self; if (args == null) { args = []; } if (!isFunction(continuable)) { throw new Error("Not a function."); } _continuations = []; link = function(go) { var continuation, found, j, len; if (isFunction(go)) { found = false; for (j = 0, len = _continuations.length; j < len; j++) { continuation = _continuations[j]; if (continuation === go) { found = true; } } if (!found) { _continuations.push(go); } } }; propagate = function() { var go; while (go = _continuations.shift()) { if (self.rejected) { go(self.error); } else { go(null, self.result); } } }; self = function(go) { return join([self], function(error, results) { if (error) { return go(error); } else { return go(null, head(results)); } }); }; self.evaluate = function(go) { link(go); if (self.settled) { return propagate(); } else if (self.evaluating) { } else { self.evaluating = true; return join(args, function(error, args) { if (error) { self.error = error; self.fulfilled = false; self.rejected = true; self.evaluating = false; return propagate(); } else { return continuable.apply(null, args.concat(function(error, result) { if (error) { self.error = error; self.fulfilled = false; self.rejected = true; self.evaluating = false; propagate(); } else { self.result = result; self.fulfilled = true; self.rejected = false; self.evaluating = false; propagate(); } self.settled = true; return self.pending = false; })); } }); } }; self.method = continuable; self.args = args; self.fulfilled = false; self.rejected = false; self.settled = false; self.pending = true; self.evaluating = false; self.isFuture = true; return self; }; join = function(args, go) { var arg, i, j, len, resultCount, results, settled, tasks; if (args.length === 0) { return go(null, []); } tasks = []; results = []; for (i = j = 0, len = args.length; j < len; i = ++j) { arg = args[i]; if (isFuture(arg)) { tasks.push({ future: arg, resultIndex: i }); } else { results[i] = arg; } } if (tasks.length === 0) { return go(null, results); } resultCount = 0; settled = false; tasks.forEach(function(task) { return task.future.evaluate(function(error, result) { if (settled) { return; } if (error) { settled = true; go(error); } else { join([result], function(error, localResults) { if (error) { settled = true; return go(error); } else { results[task.resultIndex] = head(localResults); resultCount++; if (resultCount === tasks.length) { settled = true; return go(null, results); } } }); } }); }); }; resolve = function() { var args, go, j; args = 2 <= arguments.length ? slice.call(arguments, 0, j = arguments.length - 1) : (j = 0, []), go = arguments[j++]; return join(args, function(error, results) { return go.apply(null, [error].concat(results)); }); }; createTask = function(continuable) { if (!isFunction(continuable)) { throw new Error("Not a function."); } return function() { var args; args = 1 <= arguments.length ? slice.call(arguments, 0) : []; return fork(continuable, args); }; }; seq = function(_futures) { return fork(function(go) { var futures, next, results; futures = _futures.slice(0); results = []; next = function() { var future; future = futures.shift(); if (future) { future(function(error, result) { if (error) { return go(error); } else { results.push(result); return next(); } }); } else { go(null, results); } }; next(); }); }; collect = function(futures) { return fork(join, [futures]); }; map = function(array, defer) { var element; return collect((function() { var j, len, results1; results1 = []; for (j = 0, len = array.length; j < len; j++) { element = array[j]; results1.push(defer(element)); } return results1; })()); }; forEach = function(array, defer) { var element; return seq((function() { var j, len, results1; results1 = []; for (j = 0, len = array.length; j < len; j++) { element = array[j]; results1.push(defer(element)); } return results1; })()); }; lift = function() { var f, futures, j; futures = 2 <= arguments.length ? slice.call(arguments, 0, j = arguments.length - 1) : (j = 0, []), f = arguments[j++]; return fork(function(go) { return join(futures, function(error, results) { if (error) { return go(error); } else { return go(null, f.apply(null, results)); } }); }); }; forkjoin = { async: async, task: createTask, fork: function() { var args, continuable; continuable = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; return fork(continuable, args); }, join: join, isFuture: isFuture, resolve: resolve, seq: seq, collect: collect, map: map, forEach: forEach, lift: lift }; if (typeof window !== "undefined" && window !== null) { window.forkjoin = forkjoin; } else { module.exports = forkjoin; } }).call(this);