123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /*
- Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
- Available via Academic Free License >= 2.1 OR the modified BSD license.
- see: http://dojotoolkit.org/license for details
- */
- if(!dojo._hasResource["dojox.lang.async"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
- dojo._hasResource["dojox.lang.async"] = true;
- dojo.provide("dojox.lang.async");
- (function(){
- var d = dojo, Deferred = d.Deferred, each = d.forEach, some = d.some,
- async = dojox.lang.async, aps = Array.prototype.slice,
- opts = Object.prototype.toString;
- async.seq = function(x){
- // summary:
- // Executes functions sequentially. Waits if any of them returns Deferred.
- var fs = opts.call(x) == "[object Array]" ? x : arguments;
- return function(init){
- var x = new Deferred();
- each(fs, function(f){ x.addCallback(f); });
- x.callback(init);
- return x;
- };
- };
- async.par = function(x){
- // summary:
- // Executes functions in parallel. Waits for all of them to finish.
- var fs = opts.call(x) == "[object Array]" ? x : arguments;
- return function(init){
- var results = new Array(fs.length),
- cancel = function(){
- each(results, function(v){
- if(v instanceof Deferred && v.fired < 0){
- v.cancel();
- }
- });
- },
- x = new Deferred(cancel),
- ready = fs.length;
- each(fs, function(f, i){
- var x;
- try {
- x = f(init);
- }catch(e){
- x = e;
- }
- results[i] = x;
- });
- var failed = some(results, function(v){
- if(v instanceof Error){
- cancel();
- x.errback(v);
- return true;
- }
- return false;
- });
- if(!failed){
- each(results, function(v, i){
- if(v instanceof Deferred){
- v.addCallbacks(
- function(v){
- results[i] = v;
- if(!--ready){
- x.callback(results);
- }
- },
- function(v){
- cancel();
- x.errback(v);
- }
- );
- }else{
- --ready;
- }
- });
- }
- if(!ready){
- x.callback(results);
- }
- return x;
- };
- };
- async.any = function(x){
- // summary:
- // Executes functions in parallel. As soon as one of them finishes
- // cancels the rest.
- var fs = opts.call(x) == "[object Array]" ? x : arguments;
- return function(init){
- var results = new Array(fs.length), noResult = true;
- cancel = function(index){
- each(results, function(v, i){
- if(i != index && v instanceof Deferred && v.fired < 0){
- v.cancel();
- }
- });
- },
- x = new Deferred(cancel);
- each(fs, function(f, i){
- var x;
- try {
- x = f(init);
- }catch(e){
- x = e;
- }
- results[i] = x;
- });
- var done = some(results, function(v, i){
- if(!(v instanceof Deferred)){
- cancel(i);
- x.callback(v);
- return true;
- }
- return false;
- });
- if(!done){
- each(results, function(v, i){
- v.addBoth(
- function(v){
- if(noResult){
- noResult = false;
- cancel(i);
- x.callback(v);
- }
- }
- );
- });
- }
- return x;
- };
- };
- async.select = function(cond, x){
- // summary:
- // Executes a condition, waits for it if necessary, and executes
- // Nth function from list.
- var fs = opts.call(x) == "[object Array]" ? x : aps.call(arguments, 1);
- return function(init){
- return new Deferred().addCallback(cond).addCallback(function(v){
- if(typeof v == "number" && v >= 0 && v < fs.length){
- return fs[v](init);
- }else{
- return new Error("async.select: out of range");
- }
- }).callback(init);
- };
- };
- async.ifThen = function(cond, ifTrue, ifFalse){
- // summary:
- // Executes a condition, waits for it if necessary, and executes
- // one of two functions.
- return function(init){
- return new Deferred().addCallback(cond).addCallback(function(v){
- return (v ? ifTrue : ifFalse)(init);
- }).callback(init);
- };
- };
- async.loop = function(cond, body){
- // summary:
- // Executes a condition, waits for it if necessary, and executes
- // the body, if truthy value was returned.
- // Then it repeats the cycle until the condition function returns
- // a falsy value.
- return function(init){
- var x, y = new Deferred(function(){ x.cancel(); });
- function ifErr(v){ y.errback(v); }
- function loop(v){
- if(v){
- x.addCallback(body).addCallback(setUp);
- }else{
- y.callback(v);
- }
- return v;
- }
- function setUp(init){
- x = new Deferred().
- addCallback(cond).
- addCallback(loop).
- addErrback(ifErr);
- x.callback(init);
- }
- setUp(init);
- return y;
- };
- };
- })();
- /*
- Design decisions:
- seq() - behaves like the normal Deferred callback chain.
- par() - if error, all pending Deferreds are cancelled and the error is signaled,
- otherwise return an array of all results.
- any() - just like par() but only one result is returned.
- select() - any error is returned, otherwise the selected result is returned.
- loop() - any error is returned, otherwise the last result is returned.
- */
- }
|