205 lines
4.6 KiB
JavaScript
205 lines
4.6 KiB
JavaScript
//>>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.
|
|
|
|
*/
|
|
|
|
});
|