async.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // wrapped by build app
  2. define("dojox/lang/async", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
  3. dojo.provide("dojox.lang.async");
  4. (function(){
  5. var d = dojo, Deferred = d.Deferred, each = d.forEach, some = d.some,
  6. async = dojox.lang.async, aps = Array.prototype.slice,
  7. opts = Object.prototype.toString;
  8. async.seq = function(x){
  9. // summary:
  10. // Executes functions sequentially. Waits if any of them returns Deferred.
  11. var fs = opts.call(x) == "[object Array]" ? x : arguments;
  12. return function(init){
  13. var x = new Deferred();
  14. each(fs, function(f){ x.addCallback(f); });
  15. x.callback(init);
  16. return x;
  17. };
  18. };
  19. async.par = function(x){
  20. // summary:
  21. // Executes functions in parallel. Waits for all of them to finish.
  22. var fs = opts.call(x) == "[object Array]" ? x : arguments;
  23. return function(init){
  24. var results = new Array(fs.length),
  25. cancel = function(){
  26. each(results, function(v){
  27. if(v instanceof Deferred && v.fired < 0){
  28. v.cancel();
  29. }
  30. });
  31. },
  32. x = new Deferred(cancel),
  33. ready = fs.length;
  34. each(fs, function(f, i){
  35. var x;
  36. try {
  37. x = f(init);
  38. }catch(e){
  39. x = e;
  40. }
  41. results[i] = x;
  42. });
  43. var failed = some(results, function(v){
  44. if(v instanceof Error){
  45. cancel();
  46. x.errback(v);
  47. return true;
  48. }
  49. return false;
  50. });
  51. if(!failed){
  52. each(results, function(v, i){
  53. if(v instanceof Deferred){
  54. v.addCallbacks(
  55. function(v){
  56. results[i] = v;
  57. if(!--ready){
  58. x.callback(results);
  59. }
  60. },
  61. function(v){
  62. cancel();
  63. x.errback(v);
  64. }
  65. );
  66. }else{
  67. --ready;
  68. }
  69. });
  70. }
  71. if(!ready){
  72. x.callback(results);
  73. }
  74. return x;
  75. };
  76. };
  77. async.any = function(x){
  78. // summary:
  79. // Executes functions in parallel. As soon as one of them finishes
  80. // cancels the rest.
  81. var fs = opts.call(x) == "[object Array]" ? x : arguments;
  82. return function(init){
  83. var results = new Array(fs.length), noResult = true;
  84. cancel = function(index){
  85. each(results, function(v, i){
  86. if(i != index && v instanceof Deferred && v.fired < 0){
  87. v.cancel();
  88. }
  89. });
  90. },
  91. x = new Deferred(cancel);
  92. each(fs, function(f, i){
  93. var x;
  94. try {
  95. x = f(init);
  96. }catch(e){
  97. x = e;
  98. }
  99. results[i] = x;
  100. });
  101. var done = some(results, function(v, i){
  102. if(!(v instanceof Deferred)){
  103. cancel(i);
  104. x.callback(v);
  105. return true;
  106. }
  107. return false;
  108. });
  109. if(!done){
  110. each(results, function(v, i){
  111. v.addBoth(
  112. function(v){
  113. if(noResult){
  114. noResult = false;
  115. cancel(i);
  116. x.callback(v);
  117. }
  118. }
  119. );
  120. });
  121. }
  122. return x;
  123. };
  124. };
  125. async.select = function(cond, x){
  126. // summary:
  127. // Executes a condition, waits for it if necessary, and executes
  128. // Nth function from list.
  129. var fs = opts.call(x) == "[object Array]" ? x : aps.call(arguments, 1);
  130. return function(init){
  131. return new Deferred().addCallback(cond).addCallback(function(v){
  132. if(typeof v == "number" && v >= 0 && v < fs.length){
  133. return fs[v](init);
  134. }else{
  135. return new Error("async.select: out of range");
  136. }
  137. }).callback(init);
  138. };
  139. };
  140. async.ifThen = function(cond, ifTrue, ifFalse){
  141. // summary:
  142. // Executes a condition, waits for it if necessary, and executes
  143. // one of two functions.
  144. return function(init){
  145. return new Deferred().addCallback(cond).addCallback(function(v){
  146. return (v ? ifTrue : ifFalse)(init);
  147. }).callback(init);
  148. };
  149. };
  150. async.loop = function(cond, body){
  151. // summary:
  152. // Executes a condition, waits for it if necessary, and executes
  153. // the body, if truthy value was returned.
  154. // Then it repeats the cycle until the condition function returns
  155. // a falsy value.
  156. return function(init){
  157. var x, y = new Deferred(function(){ x.cancel(); });
  158. function ifErr(v){ y.errback(v); }
  159. function loop(v){
  160. if(v){
  161. x.addCallback(body).addCallback(setUp);
  162. }else{
  163. y.callback(v);
  164. }
  165. return v;
  166. }
  167. function setUp(init){
  168. x = new Deferred().
  169. addCallback(cond).
  170. addCallback(loop).
  171. addErrback(ifErr);
  172. x.callback(init);
  173. }
  174. setUp(init);
  175. return y;
  176. };
  177. };
  178. })();
  179. /*
  180. Design decisions:
  181. seq() - behaves like the normal Deferred callback chain.
  182. par() - if error, all pending Deferreds are cancelled and the error is signaled,
  183. otherwise return an array of all results.
  184. any() - just like par() but only one result is returned.
  185. select() - any error is returned, otherwise the selected result is returned.
  186. loop() - any error is returned, otherwise the last result is returned.
  187. */
  188. });