UNPKG

fluture

Version:

FantasyLand compliant (monadic) alternative to Promises

82 lines (69 loc) 2.13 kB
import {wrapException, invalidArgumentOf} from './internal/error.js'; import {isArray} from './internal/predicates.js'; import {noop} from './internal/utils.js'; import { createInterpreter, isFuture, resolve, application1, positiveInteger, application } from './future.js'; function isFutureArray(xs){ if(!isArray(xs)) return false; for(var i = 0; i < xs.length; i++){ if(!isFuture(xs[i])) return false; } return true; } export var futureArray = { pred: isFutureArray, error: invalidArgumentOf('be an Array of valid Futures') }; export var Parallel = createInterpreter(2, 'parallel', function Parallel$interpret(rec, rej, res){ var _this = this, futures = this.$2, length = futures.length; var max = Math.min(this.$1, length), cancels = new Array(length), out = new Array(length); var cursor = 0, running = 0, blocked = false, cont = noop; function Parallel$cancel(){ rec = noop; rej = noop; res = noop; cursor = length; for(var n = 0; n < length; n++) cancels[n] && cancels[n](); } function Parallel$run(idx){ running++; cancels[idx] = futures[idx]._interpret(function Parallel$rec(e){ cont = rec; cancels[idx] = noop; Parallel$cancel(); cont(wrapException(e, _this)); }, function Parallel$rej(reason){ cont = rej; cancels[idx] = noop; Parallel$cancel(); cont(reason); }, function Parallel$res(value){ cancels[idx] = noop; out[idx] = value; running--; if(cursor === length && running === 0) res(out); else if(blocked) Parallel$drain(); }); } function Parallel$drain(){ blocked = false; while(cursor < length && running < max) Parallel$run(cursor++); blocked = true; } Parallel$drain(); return Parallel$cancel; }); var emptyArray = resolve([]); export function parallel(max){ var context1 = application1(parallel, positiveInteger, arguments); return function parallel(ms){ var context2 = application(2, parallel, futureArray, arguments, context1); return ms.length === 0 ? emptyArray : new Parallel(context2, max, ms); }; }