root/as3/ASDeferred/src/ASDeferred.as

リビジョン 216, 7.6 kB (コミッタ: munegon, コミット時期: 4 年 前)

--

  • svn:mime-type 属性の設定値: text/plain; charset=utf-8
Line 
1 /*
2  * ASDeferred Class for ActionScript3.0
3  * Copyright (c) 2008 munegon ( www.voidelement.com )
4  *
5  * Version:: 0.1
6  * License:: MIT
7  *
8  *
9  * refer to JSDeferred
10  * Copyright (c) 2007 cho45 ( www.lowreal.net )
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  * copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in
20  * all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28  * THE SOFTWARE.
29  */
30
31
32 package {
33         import flash.utils.Timer;
34         import flash.events.TimerEvent;
35        
36         public class ASDeferred {
37                 private var _next:ASDeferred;
38                
39                 public var callback:Object;
40                 public var canceller:Function;
41                
42                 public function ASDeferred() {
43                         init();
44                 }
45                
46                
47                 public function init():ASDeferred {
48                         _next = null;
49                        
50                         callback = {
51                                 ok: function( x:* ):* { return x; },
52                                 ng: function( x:* ):* { return x; }
53                         };
54                        
55                         return this;
56                 }
57                
58                
59                 public function next( func:Function ):ASDeferred {
60                         return _post("ok", func );
61                 }
62                
63                 public function error( func:Function ):ASDeferred {
64                         return _post("ng", func );
65                 }
66                
67                 public function call( value:* = null ):ASDeferred {
68                         return _fire("ok", value );
69                 }
70                
71                 public function fail( err:* = null ):ASDeferred {
72                         return _fire("ng", err );
73                 }
74                
75                 public function cancel():ASDeferred {
76                         if ( canceller is Function ) {
77                                 canceller();
78                         }
79                        
80                         return init();
81                 }
82                
83                
84                 private function _post( okng:String, func:Function ):ASDeferred {
85                         _next = new ASDeferred();
86                         _next.callback[ okng ] = func;
87                        
88                         return _next;
89                 }
90                
91                
92                 private function _fire( okng:String, value:* ):ASDeferred {
93                         var next:String = "ok";
94                        
95                         try {
96                                 value = callback[ okng ].call( this, value );
97                         } catch ( e:Error ) {
98                                 next = "ng";
99                                 value = e;
100                         }
101                        
102                         if ( value is ASDeferred ) {
103                                 value._next = _next;
104                         } else {
105                                 if ( _next ) _next._fire( next, value );
106                         }
107                        
108                         return this;
109                 }
110                
111                
112                 public static function loop( n:*, func:Function ):ASDeferred {
113                         var o:Object = {
114                                 begin : n.hasOwnProperty("begin") ? n.begin : 0,
115                                 end   : n.hasOwnProperty("end") ? n.end : n - 1,
116                                 step  : n.hasOwnProperty("step") ? n.step : 1,
117                                 last  : false,
118                                 prev  : null
119                         };
120                        
121                         var ret:*;
122                         var step:int = o.step;
123                        
124                        
125                         return ASDeferred.next( function():ASDeferred {
126                                 function _loop( i:int ):* {
127                                         if ( i <= o.end ) {
128                                                 if ( i + step > o.end ) {
129                                                         o.last = true;
130                                                         o.step = o.end - i + 1;
131                                                 }
132                                                
133                                                 o.prev = ret;
134                                                 ret = func.apply( this, [ i, o ] );
135                                                
136                                                 if ( ret is ASDeferred ) {
137                                                         return ret.next( function( r:* ):* {
138                                                                 ret = r;
139                                                                 return _loop( i + step );
140                                                         });
141                                                 } else {
142                                                         _loop( i + step );
143                                                 }
144                                         } else {
145                                                 return ret;
146                                         }
147                                 }
148                                 return _loop( o.begin );
149                         });
150                 }
151                
152                 public static function parallel( dl:Object ):ASDeferred {
153                         var ret:ASDeferred = new ASDeferred();
154                         var values:* = ( dl is Array ) ? [] : {};
155                         var num:int = 0;
156                        
157                         for ( var i:String in dl ) {
158                                 if ( dl.hasOwnProperty( i ) ) {
159                                         ( function( d:ASDeferred, i:String ):void {
160                                                 d.next( function( v:* ):void {
161                                                         values[i] = v;
162                                                        
163                                                         if ( --num <= 0 ) {
164                                                                 ret.call( values );
165                                                         }
166                                                 }).error( function( e:* ):void {
167                                                         ret.fail( e );
168                                                 });
169                                                 num++;
170                                                
171 /*
172                                                 // parallel を直列で定義できるようにするための挿入コード
173                                                 var timer:Timer = new Timer( 0, 1 );
174                                                 var complete:Function = function( e:TimerEvent ):void {
175                                                         timer.removeEventListener( e.type, arguments.callee );
176                                                         d.call();
177                                                 }
178                                                 timer.addEventListener( TimerEvent.TIMER_COMPLETE, complete );
179                                                 timer.start();
180                                                
181                                                 d.canceller = function():void {
182                                                         try {
183                                                                 timer.stop();
184                                                                 timer.removeEventListener( TimerEvent.TIMER_COMPLETE, complete );
185                                                         } catch ( e:Error ) {
186                                                                
187                                                         }
188                                                 }
189 //*/
190                                         })( dl[i], i );
191                                 }
192                         }
193                        
194                         if ( num == 0 ) {
195                                 ASDeferred.next( function():void { ret.call() } );
196                         }
197                        
198                         ret.canceller = function():void {
199                                 for ( var i:String in dl ) {
200                                         if ( dl.hasOwnProperty( i ) ) {
201                                                 dl[i].cancel();
202                                         }
203                                 }
204                         }
205                        
206                         return ret;
207                 }
208                
209                
210                 public static function wait( n:Number ):ASDeferred {
211                         var d:ASDeferred = new ASDeferred();
212                         var t:Date = new Date();
213                        
214                         var timer:Timer = new Timer( n*1000, 1 );
215                         var complete:Function = function( e:TimerEvent ):void {
216                                 timer.removeEventListener( e.type, arguments.callee );
217                                 d.call( new Date().getTime() - t.getTime() );
218                         }
219                         timer.addEventListener( TimerEvent.TIMER_COMPLETE, complete );
220                         timer.start();
221                        
222                         d.canceller = function():void {
223                                 try {
224                                         timer.stop();
225                                         timer.removeEventListener( TimerEvent.TIMER_COMPLETE, complete );
226                                 } catch ( e:Error ) {
227                                        
228                                 }
229                         }
230                        
231                         return d;
232                 }
233                
234                
235                 public function wait( n:Number ):ASDeferred {
236                         return next( function():ASDeferred { return ASDeferred.wait( n ) } );
237                 }
238                
239                 public function loop( n:*, func:Function ):ASDeferred {
240                         return next( function():ASDeferred { return ASDeferred.loop( n, func ) } );
241                 }
242                
243                 // parallel を直列で繋げられるようにするための追加メソッド
244                 public function parallel( dl:Object ):ASDeferred {
245                         return next( function():ASDeferred { return ASDeferred.parallel( dl ) } );
246                 }
247                
248                 public static function wrap( func:Function ):Function {
249                         return function( ...args:Array ):Function {
250                                 return function():Function {
251                                         return func.apply( null, args );
252                                 }
253                         }
254                 }
255                
256                
257                 public static function next( func:Function ):ASDeferred {
258                         var d:ASDeferred = new ASDeferred();
259                        
260                         var timer:Timer = new Timer( 0, 1 );
261                         var complete:Function = function( e:TimerEvent ):void {
262                                 timer.removeEventListener( e.type, arguments.callee );
263                                 d.call();
264                         }
265                         timer.addEventListener( TimerEvent.TIMER_COMPLETE, complete );
266                         timer.start();
267                        
268                         if ( func != null ) d.callback.ok = func;
269                        
270                         d.canceller = function():void {
271                                 try {
272                                         timer.stop();
273                                         timer.removeEventListener( TimerEvent.TIMER_COMPLETE, complete );
274                                 } catch ( e:Error ) {
275                                        
276                                 }
277                         }
278                        
279                         return d;
280                 }
281                
282                
283                 public static function call( func:Function, ...args:Array ):ASDeferred {
284                         return ASDeferred.next(
285                                 function():* {
286                                         return func.apply( this, args );
287                                 }
288                         );
289                 }
290                
291                 public static function define( obj:Object = null, list:Array = null ):Class {
292                         if ( !list ) list = ["parallel", "wait", "next", "call", "loop"];
293                         if ( !obj ) obj = ( function():ASDeferred { return this } )();
294                        
295                         for ( var i:int = 0; i < list.length; ++i ) {
296                                 obj[ list[i] ] = ASDeferred[ list[i] ];
297                         }
298                        
299                         return ASDeferred;
300                 }
301         }
302 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。