source: Dev/branches/rest-dojo-ui/client/qed/lib/async.js @ 420

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

We can store answers for surveys now!

Introduces SurveyRun?, which can be edited. Workflow not quite clear yet. A
running survey can be accessed to leave a response. When the response
has an ID, it is loaded (used for closed surveys and continuations). A
researcher cannot create responses yet. He should also be able to add
comments to responses (that he creates).

Introduced caching of store requests.

Factored out path matching and formatting.

Put object creation in separate classes, to localize model/storage
dependency. Not consistent at the moment.

File size: 3.8 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            running && running.cancel && !running.isFulfilled() && running.cancel();
25            d.reject(err);
26        }
27
28        function update(fs,arg) {
29            if ( cancelled ) return;
30            if ( fs.length > 0 ) {
31                try {
32                    var f = fs.shift();
33                    running = when(f.call(ctx,arg))
34                    .then(function(res){
35                        update(fs,res);
36                    },function(err){
37                        cancel(err);
38                    });
39                } catch(err) {
40                    cancel(err);
41                }
42            } else {
43                d.resolve(arg);
44            }
45        }
46
47        update(functions);
48
49        return d.promise;
50    }
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     */
104    function forEach(list,callback,ctx) {
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);
119    }
120
121    return {
122        seq: seq,
123        par: par,
124        forEach: forEach,
125        map: map
126    };
127
128});
Note: See TracBrowser for help on using the repository browser.