summaryrefslogtreecommitdiff
path: root/js/dojo/dojox/lang/async.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/dojo/dojox/lang/async.js')
-rw-r--r--js/dojo/dojox/lang/async.js204
1 files changed, 204 insertions, 0 deletions
diff --git a/js/dojo/dojox/lang/async.js b/js/dojo/dojox/lang/async.js
new file mode 100644
index 0000000..26e901d
--- /dev/null
+++ b/js/dojo/dojox/lang/async.js
@@ -0,0 +1,204 @@
+//>>built
+// wrapped by build app
+define("dojox/lang/async", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+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.
+
+*/
+
+});