Changeset 420 for Dev/branches/rest-dojo-ui/client/qed/lib/async.js
- Timestamp:
- 12/16/12 20:07:35 (12 years ago)
- Location:
- Dev/branches/rest-dojo-ui/client/qed/lib
- Files:
-
- 1 added
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
Dev/branches/rest-dojo-ui/client/qed/lib/async.js
r415 r420 1 1 define([ 2 'dojo/Deferred', 3 ],function(Deferred){ 2 'dojo/_base/array', 3 'dojo/_base/lang', 4 'dojo/when', 5 'dojo/Deferred' 6 ],function(array,lang,when,Deferred){ 4 7 5 function seq(functions) { 8 /** Execute possible async functions in sequence 9 * Execute functions in order. When a function returns a Promise, 10 * the next function is only executed when the promise resolves. 11 * If the function returns a value, the next function is executed 12 * synchronously. The return value of every function is passed as argument 13 * to the next. 14 * Returns the return value of the last function in the chain. 15 */ 16 function seq(functions,ctx) { 6 17 var d = new Deferred(); 7 (function stepper(fs,arg) { 18 19 var cancelled = false; 20 var running = null; 21 function cancel(err) { 22 if ( cancelled ) return; 23 cancelled = true; 24 running && running.cancel && !running.isFulfilled() && running.cancel(); 25 d.reject(err); 26 } 27 28 function update(fs,arg) { 29 if ( cancelled ) return; 8 30 if ( fs.length > 0 ) { 9 31 try { 10 32 var f = fs.shift(); 11 var ret = f(arg); 12 if ( ret && ret.then ) { 13 ret.then(function(ret){ 14 stepper(fs,ret); 15 }); 16 } else { 17 stepper(fs,ret); 18 } 33 running = when(f.call(ctx,arg)) 34 .then(function(res){ 35 update(fs,res); 36 },function(err){ 37 cancel(err); 38 }); 19 39 } catch(err) { 20 d.reject(err);40 cancel(err); 21 41 } 22 42 } else { 23 d.resolve( );43 d.resolve(arg); 24 44 } 25 })(functions); 45 } 46 47 update(functions); 48 26 49 return d.promise; 27 50 } 28 51 52 /** Execute possible async functions in parallel 53 * Execute all functions in parallel, resolve only when all have resolved. 54 * NB. When a function is not async, it will fully complete before the next 55 * async function is started. If you mix async and non async functions, put 56 * the sync functions last to fully exploit the async ones. 57 * Return an array with all the return values of the functions. 58 */ 59 function par(functions,ctx) { 60 var d = new Deferred(cancel); 61 62 var cancelled = false; 63 var running = []; 64 function cancel(err) { 65 if (cancelled) return; 66 cancelled = true; 67 array.forEach(running,function(running){ 68 running && running.cancel && !running.isFulfilled() && running.cancel(); 69 }); 70 d.reject(err); 71 } 72 73 var results = []; 74 var left = functions.length; 75 function update(res,idx) { 76 if (cancelled) return; 77 results[idx] = res; 78 left -= 1; // Works because/as long as AJAX/JS is single-threaded. 79 if ( left === 0 ) { 80 d.resolve(results); 81 } 82 } 83 84 array.forEach(functions,function(f,idx){ 85 if (cancelled) return; 86 try { 87 running.push(when(f.call(ctx)).then(function(res){ 88 update(res,idx); 89 },function(err){ 90 cancel(err); 91 })); 92 } catch (err) { 93 cancel(); 94 } 95 }); 96 97 return d.promise; 98 } 99 100 /** Iterate over an array with async callback 101 * Execute the callback and if it's async, wait until it's finished before 102 * executing the next one. 103 */ 29 104 function forEach(list,callback,ctx) { 30 var d = new Deferred(); 31 (function stepper(list,idx){ 32 if ( list.length > 0 ) { 33 var el = list.shift(); 34 var ret = callback.call(ctx,el,idx); 35 if ( ret && ret.then ) { 36 ret.then(function(){ 37 stepper(list,idx+1); 38 }); 39 } else { 40 stepper(list,idx+1); 41 } 42 } else { 43 d.resolve(); 44 } 45 })(list,0); 46 return d.promise; 105 var fs = array.map(list,function(item,index,items){ 106 return lang.hitch(ctx,callback,item,index,items); 107 }); 108 return seq(fs); 109 } 110 111 /** Map a list, possible async 112 * Map every element of a list, returning a promise to the mapped list. 113 */ 114 function map(list,callback,ctx) { 115 var fs = array.map(list,function(item,index,items){ 116 return lang.hitch(ctx,callback,item,index,items); 117 }); 118 return par(fs); 47 119 } 48 120 49 121 return { 50 122 seq: seq, 51 forEach: forEach 123 par: par, 124 forEach: forEach, 125 map: map 52 126 }; 53 127
Note: See TracChangeset
for help on using the changeset viewer.