source: Dev/trunk/client/qed/lib/async.js @ 426

Last change on this file since 426 was 426, checked in by hendrikvanantwerpen, 12 years ago

Added grunt tasks and code cleanup.

Added grunt for less and jshint procesing.
Cleanup of code to pass jshint (one bug found :).

File size: 4.0 KB
Line 
1define([
2    'dojo/_base/array',
3    'dojo/_base/lang',
4    'dojo/when',
5    'dojo/Deferred'
6],function(array,lang,when,Deferred){
7
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) {
17        var d = new Deferred();
18
19        var cancelled = false;
20        var running = null;
21        function cancel(err) {
22            if ( cancelled ) { return; }
23            cancelled = true;
24            if ( running && running.cancel && !running.isFulfilled() ) {
25                running.cancel();
26            }
27            d.reject(err);
28        }
29
30        function update(fs,arg) {
31            if ( cancelled ) { return; }
32            if ( fs.length > 0 ) {
33                try {
34                    var f = fs.shift();
35                    running = when(f.call(ctx,arg))
36                    .then(function(res){
37                        update(fs,res);
38                    },function(err){
39                        cancel(err);
40                    });
41                } catch(err) {
42                    cancel(err);
43                }
44            } else {
45                d.resolve(arg);
46            }
47        }
48
49        update(functions);
50
51        return d.promise;
52    }
53
54    /** Execute possible async functions in parallel
55     * Execute all functions in parallel, resolve only when all have resolved.
56     * NB. When a function is not async, it will fully complete before the next
57     * async function is started. If you mix async and non async functions, put
58     * the sync functions last to fully exploit the async ones.
59     * Return an array with all the return values of the functions.
60     */
61    function par(functions,ctx) {
62        var d; // later: Deferred
63       
64        var cancelled = false;
65        var running = [];
66        function cancel(err) {
67            if (cancelled) { return; }
68            cancelled = true;
69            array.forEach(running,function(running){
70                if ( running && running.cancel && !running.isFulfilled() ) {
71                    running.cancel();
72                }
73            });
74            d.reject(err);
75        }
76
77        d = new Deferred(cancel);
78
79        var results = [];
80        var left = functions.length;
81        function update(res,idx) {
82            if (cancelled) { return; }
83            results[idx] = res;
84            left -= 1; // Works because/as long as AJAX/JS is single-threaded.
85            if ( left === 0 ) {
86                d.resolve(results);
87            }
88        }
89
90        array.forEach(functions,function(f,idx){
91            if (cancelled) { return; }
92            try {
93                running.push(when(f.call(ctx)).then(function(res){
94                    update(res,idx);
95                },function(err){
96                    cancel(err);
97                }));
98            } catch (err) {
99                cancel();
100            }
101        });
102
103        return d.promise;
104    }
105
106    /** Iterate over an array with async callback
107     * Execute the callback and if it's async, wait until it's finished before
108     * executing the next one.
109     */
110    function forEach(list,callback,ctx) {
111        var fs = array.map(list,function(item,index,items){
112            return lang.hitch(ctx,callback,item,index,items);
113        });
114        return seq(fs);
115    }
116
117    /** Map a list, possible async
118     * Map every element of a list, returning a promise to the mapped list.
119     */
120    function map(list,callback,ctx) {
121        var fs = array.map(list,function(item,index,items){
122            return lang.hitch(ctx,callback,item,index,items);
123        });
124        return par(fs);
125    }
126
127    return {
128        seq: seq,
129        par: par,
130        forEach: forEach,
131        map: map
132    };
133
134});
Note: See TracBrowser for help on using the repository browser.