source: Dev/branches/rest-dojo-ui/client/dojox/lang/async.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

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