Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dojox.lang new module: async (a helper for event-driven programming),…
… !strict, refs #10625. git-svn-id: http://svn.dojotoolkit.org/src/dojox/trunk@21140 560b804f-0ae3-0310-86f3-f6aa0a117693
- Loading branch information
Showing
7 changed files
with
434 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
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); | ||
x.addCallback(setUp); | ||
}else{ | ||
y.callback(v); | ||
} | ||
return v; | ||
} | ||
function setUp(init){ | ||
x = new Deferred(). | ||
addCallback(cond). | ||
addCallback(loop). | ||
addErrback(ifErr). | ||
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. | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
dojo.provide("dojox.lang.async.event"); | ||
|
||
// Source of Deferred for events | ||
|
||
(function(){ | ||
var d = dojo, event = dojox.lang.async.event; | ||
|
||
event.from = function(src, name){ | ||
return function(){ | ||
var h, cancel = function(){ | ||
if(h){ | ||
d.disconnect(h); | ||
h = null; | ||
} | ||
}, | ||
x = new d.Deferred(cancel); | ||
h = d.connect(src, name, function(evt){ | ||
cancel(); | ||
x.callback(evt); | ||
}); | ||
return x; | ||
}; | ||
}; | ||
|
||
event.failOn = function(src, name){ | ||
return function(){ | ||
var h, cancel = function(){ | ||
if(h){ | ||
d.disconnect(h); | ||
h = null; | ||
} | ||
}, | ||
x = new d.Deferred(cancel); | ||
h = d.connect(src, name, function(evt){ | ||
cancel(); | ||
x.errback(new Error(evt)); | ||
}); | ||
return x; | ||
}; | ||
}; | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
dojo.provide("dojox.lang.async.timeout"); | ||
|
||
// Source of Deferred for timeouts | ||
|
||
(function(){ | ||
var d = dojo, timeout = dojox.lang.async.timeout; | ||
|
||
timeout.from = function(ms){ | ||
return function(){ | ||
var h, cancel = function(){ | ||
if(h){ | ||
clearTimeout(h); | ||
h = null; | ||
} | ||
}, | ||
x = new d.Deferred(cancel); | ||
h = setTimeout(function(){ | ||
cancel(); | ||
x.callback(ms); | ||
}, ms); | ||
return x; | ||
}; | ||
}; | ||
|
||
timeout.failOn = function(ms){ | ||
return function(){ | ||
var h, cancel = function(){ | ||
if(h){ | ||
clearTimeout(h); | ||
h = null; | ||
} | ||
}, | ||
x = new d.Deferred(cancel); | ||
h = setTimeout(function(){ | ||
cancel(); | ||
x.errback(ms); | ||
}, ms); | ||
return x; | ||
}; | ||
}; | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
dojo.provide("dojox.lang.async.topic"); | ||
|
||
// Source of Deferred for topics | ||
|
||
(function(){ | ||
var d = dojo, topic = dojox.lang.async.topic; | ||
|
||
topic.from = function(topic){ | ||
return function(){ | ||
var h, cancel = function(){ | ||
if(h){ | ||
d.unsubscribe(h); | ||
h = null; | ||
} | ||
}, | ||
x = new d.Deferred(cancel); | ||
h = d.subscribe(topic, function(){ | ||
cancel(); | ||
x.callback(arguments); | ||
}); | ||
return x; | ||
}; | ||
}; | ||
|
||
topic.failOn = function(topic){ | ||
return function(){ | ||
var h, cancel = function(){ | ||
if(h){ | ||
d.unsubscribe(h); | ||
h = null; | ||
} | ||
}, | ||
x = new d.Deferred(cancel); | ||
h = d.subscribe(topic, function(evt){ | ||
cancel(); | ||
x.errback(new Error(arguments)); | ||
}); | ||
return x; | ||
}; | ||
}; | ||
})(); |
Oops, something went wrong.