forkjoin
Version:
Fork/Join primitives for async programming (experimental)
1 lines • 4.53 kB
JavaScript
(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);