Permalink
Browse files

[Invalidate] support for non-UIComponents and removed promise features.

Removed AS3 promises (Promise Specification C / jQuery standard) classes
- Now in AS3 promises repository
Fixed InvalidationTracker
- now [Invalidate] on non-UIComponents
- now properly invokes optional callback
- now throttles callback to defer invocation 1-2 frames
  • Loading branch information...
1 parent 6fe69ff commit d46d6cf72ea4efbb7222b1bcfb851a4f37009cef @ThomasBurleson ThomasBurleson committed Apr 27, 2012
View
2 .actionScriptProperties
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<actionScriptProperties analytics="false" mainApplicationPath="foundation.as" projectUUID="c404e846-5879-4b64-92d8-b5a70efef147" version="10">
- <compiler additionalCompilerArguments="-locale en_US &#10;-keep-as3-metadata+=Invalidate &#10;-define=CONFIG::FLEX3,false&#10;-define=CONFIG::FLEX4,true" autoRSLOrdering="true" copyDependentFiles="false" flex3CompatMode="false" flexSDK="Flex 4.5.1" fteInMXComponents="false" generateAccessible="false" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="false" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="bin" removeUnusedRSL="true" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
+ <compiler additionalCompilerArguments="-locale en_US &#10;-keep-as3-metadata+=Invalidate &#10;-define=CONFIG::FLEX3,false&#10;-define=CONFIG::FLEX4,true" autoRSLOrdering="true" copyDependentFiles="false" flex3CompatMode="false" flexSDK="Flex 4.6.0" fteInMXComponents="false" generateAccessible="false" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="false" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="bin" removeUnusedRSL="true" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
<compilerSourcePath/>
<libraryPath defaultLinkType="0">
<libraryPathEntry kind="4" path="">
View
5 .flexLibProperties
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<flexLibProperties includeAllClasses="false" useMultiPlatformConfig="false" version="3">
+<flexLibProperties includeAllClasses="true" useMultiPlatformConfig="false" version="3">
<includeClasses>
<classEntry path="asset.image.cursor.CursorAsset"/>
<classEntry path="asset.image.search.SearchAsset"/>
@@ -107,9 +107,6 @@
<classEntry path="com.codecatalyst.util.invalidation.InvalidationTrackedProperty"/>
<classEntry path="com.codecatalyst.util.invalidation.InvalidationTracker"/>
<classEntry path="com.codecatalyst.util.invalidation.mxml.InvalidationTracker"/>
- <classEntry path="com.codecatalyst.util.promise.Deferred"/>
- <classEntry path="com.codecatalyst.util.promise.Promise"/>
- <classEntry path="com.codecatalyst.util.promise.PromiseUtil"/>
<classEntry path="qs.charts.DashedAreaRenderer"/>
<classEntry path="qs.charts.DashedLineRenderer"/>
<classEntry path="qs.utils.GraphicsUtils"/>
View
BIN bin/flex-extensions.swc
Binary file not shown.
View
BIN bin/flex-extensions_sdk3.6.swc
Binary file not shown.
View
BIN bin/flex-extensions_sdk4.5.1.swc
Binary file not shown.
View
17 src/com/codecatalyst/util/AsyncTokenUtil.as
@@ -22,9 +22,6 @@
package com.codecatalyst.util
{
- import com.codecatalyst.util.promise.Deferred;
- import com.codecatalyst.util.promise.Promise;
-
import mx.rpc.AsyncToken;
import mx.rpc.IResponder;
import mx.rpc.Responder;
@@ -101,19 +98,5 @@ package com.codecatalyst.util
return proxyToken;
}
- /**
- * Create a Promise for the specified AsyncToken.
- *
- * @see com.codecatalyst.util.promise.Promise
- */
- public static function createPromise( token:AsyncToken ):Promise
- {
- var deferred:Deferred = new Deferred();
-
- var responder:Responder = new Responder( deferred.resolve, deferred.reject );
- token.addResponder( responder );
-
- return deferred.promise;
- }
}
}
View
22 src/com/codecatalyst/util/invalidation/InvalidationTrackedProperty.as
@@ -102,6 +102,12 @@ package com.codecatalyst.util.invalidation
return _previousValue;
}
+ /**
+ * Support to defer `reset()` when callbacks on non-IInvalidating are used.
+ * Set to `false` to allow "throttled" callbacks to used; @see InvalidationTracker::applyThrottler()
+ */
+ public var autoReset : Boolean = true;
+
// ========================================
// Constructor
// ========================================
@@ -242,7 +248,7 @@ package com.codecatalyst.util.invalidation
*/
public function invalidate():void
{
- if (_invalidated == false)
+ if ( _invalidated == false )
{
_invalidated = true;
@@ -270,11 +276,16 @@ package com.codecatalyst.util.invalidation
if ( callback != null )
{
var currentValue:* = PropertyUtil.getObjectPropertyValue( source, propertyName );
-
+
if ( callback.length == 3 )
callback( propertyName, previousValue, currentValue );
else
callback();
+
+ if ( !(source is IInvalidating) && autoReset )
+ {
+ reset();
+ }
}
}
@@ -283,9 +294,8 @@ package com.codecatalyst.util.invalidation
* Reset this invalidated tracked property.
*/
public function reset():void
- {
- _invalidated = false;
-
+ {
+ _invalidated = false;
_previousValue = PropertyUtil.getObjectPropertyValue( source, propertyName );
}
@@ -312,5 +322,7 @@ package com.codecatalyst.util.invalidation
}
private var _customEventName : String;
+
+
}
}
View
58 src/com/codecatalyst/util/invalidation/InvalidationTracker.as
@@ -22,11 +22,13 @@
package com.codecatalyst.util.invalidation
{
+ import com.codecatalyst.util.DelayedCall;
import com.codecatalyst.util.MetadataUtil;
import flash.events.IEventDispatcher;
import flash.utils.Dictionary;
+ import mx.core.IInvalidating;
import mx.events.FlexEvent;
import mx.utils.DescribeTypeCache;
import mx.utils.StringUtil;
@@ -76,16 +78,64 @@ package com.codecatalyst.util.invalidation
/**
* Constructor.
*/
- public function InvalidationTracker( source:IEventDispatcher, callback:Function = null )
+ public function InvalidationTracker( source:IEventDispatcher, callback:Function = null, enableThrottle:Boolean=false )
{
super();
this.source = source;
- this.callback = callback;
+ this.callback = applyThrottle( callback, enableThrottle );
setup();
}
+ /**
+ * Defer notification via explicit callback for 1-2 frames IF the source
+ * is not IInvalidating and user has explicitly requested throttling.
+ *
+ * NOTE: only callbacks with zero-args can be throttled.
+ */
+ private function applyThrottle(callback:Function, enable:Boolean) : Function
+ {
+ var allowed : Boolean = callback && enable && !(source is IInvalidating);
+ var delayed : Boolean = false;
+
+ /**
+ * Since the throttler can be invoked n-times [while deferred]
+ * each time with different (propertyName, ...) values.
+ * So we restrict throttling only for callbacks with zero-arguments!
+ */
+ var throttler : Function = function() :void
+ {
+ // !! The scope of throttler callback is an ITP instance
+ this["autoReset"] = false;
+
+ // Ignore current callback if `real` is still pending.
+ if ( !delayed )
+ {
+ delayed = true;
+
+ // Defer notification for 1-2 frames...
+ DelayedCall.schedule( function():void
+ {
+ delayed = false;
+
+ // Call `real` callback 1x
+ callback();
+
+ // now force reset() on all ITP instances
+ for each ( var inst:InvalidationTrackedProperty in trackedProperties )
+ {
+ inst.reset();
+ }
+
+ }, [], 45);
+ }
+
+ };
+
+ return allowed ? throttler : callback;
+ }
+
// ========================================
// Public methods
// ========================================
@@ -228,7 +278,9 @@ package com.codecatalyst.util.invalidation
invalidateMetadataOptions
.split(",")
- .map( function ( item:String, index:int, array:Array ):uint {
+ .map( function ( item:String, index:int, array:Array ):uint {
+ if (item == "") return InvalidationFlags.NONE;
+
switch( StringUtil.trim( item ).toLowerCase() )
{
case "displaylist": return InvalidationFlags.DISPLAY_LIST;
View
550 src/com/codecatalyst/util/promise/Deferred.as
@@ -1,550 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2011 CodeCatalyst, LLC - http://www.codecatalyst.com/
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-////////////////////////////////////////////////////////////////////////////////
-
-package com.codecatalyst.util.promise
-{
- import flash.events.Event;
- import flash.events.EventDispatcher;
-
- /**
- * Deferred.
- *
- * A chainable utility object that can register multiple callbacks into callback queues, invoke callback queues,
- * and relay the success, failure and progress state of any synchronous or asynchronous operation.
- *
- * @see com.codecatalyst.util.promise.Promise
- *
- * Inspired by jQuery's Deferred implementation.
- *
- * @author John Yanarella
- */
- public class Deferred extends EventDispatcher
- {
- // ========================================
- // Protected constants
- // ========================================
-
- /**
- * Internal state change Event type.
- */
- internal static const STATE_CHANGED:String = "stateChanged";
-
- // ========================================
- // Protected constants
- // ========================================
-
- /**
- * State for a Deferred that has not yet been resolved, rejected or cancelled.
- */
- protected static const PENDING_STATE:String = "pending";
-
- /**
- * State for a Deferred that has been resolved.
- */
- protected static const SUCCEEDED_STATE:String = "succeeded";
-
- /**
- * State for a Deferred that has been rejected.
- */
- protected static const FAILED_STATE:String = "failed";
-
- /**
- * State for a Deferred that has been cancelled.
- */
- protected static const CANCELLED_STATE:String = "cancelled";
-
- // ========================================
- // Public properties
- // ========================================
-
- /**
- * Promise.
- */
- public function get promise():Promise
- {
- return _promise;
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Indicates this Deferred has not yet been resolved, rejected or cancelled.
- */
- public function get pending():Boolean
- {
- return ( state == PENDING_STATE );
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Indicates this Deferred has been resolved.
- */
- public function get succeeded():Boolean
- {
- return ( state == SUCCEEDED_STATE );
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Indicates this Deferred has been rejected.
- */
- public function get failed():Boolean
- {
- return ( state == FAILED_STATE );
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Indicates this Deferred has been cancelled.
- */
- public function get cancelled():Boolean
- {
- return ( state == CANCELLED_STATE );
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Progress supplied when this Deferred was updated.
- */
- public function get progress():*
- {
- return _progress;
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Result supplied when this Deferred was resolved.
- */
- public function get result():*
- {
- return _result;
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Error supplied when this Deferred was rejected.
- */
- public function get error():*
- {
- return _error;
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Reason supplied when this Deferred was cancelled.
- */
- public function get reason():*
- {
- return _reason;
- }
-
- // ========================================
- // Protected properties
- // ========================================
-
- /**
- * Backing variable for <code>promise</code> property.
- */
- protected var _promise:Promise = null;
-
- /**
- * Backing variable for <code>progress</code.
- */
- protected var _progress:* = null;
-
- /**
- * Backing variable for <code>result</code.
- */
- protected var _result:* = null;
-
- /**
- * Backing variable for <code>error</code.
- */
- protected var _error:* = null;
-
- /**
- * Backing variable for <code>reason</code.
- */
- protected var _reason:* = null;
-
- /**
- * Deferred state.
- *
- * @see #STATE_PENDING
- * @see #STATE_SUCCEEDED
- * @see #STATE_FAILED
- * @see #STATE_CANCELLED
- */
- protected var state:String = Deferred.PENDING_STATE;
-
- /**
- * Callbacks to be called when this Deferred is updated.
- */
- protected var progressCallbacks:Array = [];
-
- /**
- * Callbacks to be called when this Deferred is resolved.
- */
- protected var resultCallbacks:Array = [];
-
- /**
- * Callbacks to be called when this Deferred is rejected.
- */
- protected var errorCallbacks:Array = [];
-
- /**
- * Callbacks to be called when this Deferred is cancelled.
- */
- protected var cancelCallbacks:Array = [];
-
- /**
- * Callbacks to be called when this Deferred is resolved or rejected.
- */
- protected var alwaysCallbacks:Array = [];
-
- // ========================================
- // Constructor
- // ========================================
-
- /**
- * Constructor.
- */
- public function Deferred()
- {
- super();
-
- _promise = new Promise( this );
- }
-
- // ========================================
- // Public methods
- // ========================================
-
- /**
- * Register callbacks to be called when this Deferred is resolved, rejected, cancelled and updated.
- */
- public function then( resultCallback:Function, errorCallback:Function = null, progressCallback:Function = null, cancelCallback:Function = null ):Deferred
- {
- onResult( resultCallback );
- onError( errorCallback );
- onProgress( progressCallback );
- onCancel( cancelCallback );
-
- return this;
- }
-
- /**
- * Registers a callback to be called when this Deferred is either resolved, rejected or cancelled.
- */
- public function always( alwaysCallback:Function ):Deferred
- {
- if ( alwaysCallback != null )
- {
- if ( pending )
- {
- alwaysCallbacks.push( alwaysCallback );
- }
- else if ( succeeded )
- {
- notify( [ alwaysCallback ], result );
- }
- else if ( failed )
- {
- notify( [ alwaysCallback ], error );
- }
- else if ( cancelled )
- {
- notify( [ alwaysCallback ], reason );
- }
- }
-
- return this;
- }
-
- /**
- * Utility method to filter and/or chain Deferreds.
- */
- public function pipe( resultCallback:Function, errorCallback:Function = null ):Promise
- {
- var deferred:Deferred = new Deferred();
-
- then(
- function ( result:* ):void
- {
- if ( resultCallback != null )
- {
- var returnValue:* = resultCallback( result );
- if ( returnValue is Deferred )
- {
- returnValue.promise.then( deferred.resolve, deferred.reject, deferred.update, deferred.cancel );
- }
- else if ( returnValue is Promise )
- {
- returnValue.then( deferred.resolve, deferred.reject, deferred.update, deferred.cancel );
- }
- else
- {
- deferred.resolve( returnValue );
- }
- }
- else
- {
- deferred.resolve( result );
- }
- },
- function ( error:* ):void
- {
- if ( errorCallback != null )
- {
- var returnValue:* = errorCallback( error );
- if ( returnValue is Deferred )
- {
- returnValue.promise.then( deferred.resolve, deferred.reject, deferred.update, deferred.cancel );
- }
- else if ( returnValue is Promise )
- {
- returnValue.then( deferred.resolve, deferred.reject, deferred.update, deferred.cancel );
- }
- else
- {
- deferred.reject( returnValue );
- }
- }
- else
- {
- deferred.reject( error );
- }
- },
- function ( update:* ):void
- {
- deferred.update( update );
- },
- function ( reason:* ):void
- {
- deferred.cancel( reason );
- }
- );
-
- return deferred.promise;
- }
-
- /**
- * Registers a callback to be called when this Deferred is updated.
- */
- public function onProgress( progressCallback:Function ):Deferred
- {
- if ( progressCallback != null )
- {
- if ( pending )
- {
- progressCallbacks.push( progressCallback );
-
- if ( progress != null )
- notify( [ progressCallback ], progress );
- }
- }
-
- return this;
- }
-
- /**
- * Registers a callback to be called when this Deferred is resolved.
- */
- public function onResult( resultCallback:Function ):Deferred
- {
- if ( resultCallback != null )
- {
- if ( pending )
- {
- resultCallbacks.push( resultCallback );
- }
- else if ( succeeded )
- {
- notify( [ resultCallback ], result );
- }
- }
-
- return this;
- }
-
- /**
- * Registers a callback to be called when this Deferred is rejected.
- */
- public function onError( errorCallback:Function ):Deferred
- {
- if ( errorCallback != null )
- {
- if ( pending )
- {
- errorCallbacks.push( errorCallback );
- }
- else if ( failed )
- {
- notify( [ errorCallback ], error );
- }
- }
-
- return this;
- }
-
- /**
- * Registers a callback to be called when this Deferred is cancelled.
- */
- public function onCancel( cancelCallback:Function ):Deferred
- {
- if ( cancelCallback != null )
- {
- if ( pending )
- {
- cancelCallbacks.push( cancelCallback );
- }
- else if ( failed )
- {
- notify( [ cancelCallback ], reason );
- }
- }
-
- return this;
- }
-
- /**
- * Update this Deferred and notify relevant callbacks.
- */
- public function update( progress:* ):Deferred
- {
- if ( pending )
- {
- _progress = progress;
-
- notify( progressCallbacks, progress );
- }
-
- return this;
- }
-
- /**
- * Resolve this Deferred and notify relevant callbacks.
- */
- public function resolve( result:* ):Deferred
- {
- if ( pending )
- {
- _result = result;
- setState( Deferred.SUCCEEDED_STATE );
-
- notify( resultCallbacks.concat( alwaysCallbacks ), result );
- releaseCallbacks();
- }
-
- return this;
- }
-
- /**
- * Reject this Deferred and notify relevant callbacks.
- */
- public function reject( error:* ):Deferred
- {
- if ( pending )
- {
- _error = error;
- setState( Deferred.FAILED_STATE );
-
- notify( errorCallbacks.concat( alwaysCallbacks ), error );
- releaseCallbacks();
- }
-
- return this;
- }
-
- /**
- * Cancel this Deferred and notify relevant callbacks.
- */
- public function cancel( reason:* = null ):Deferred
- {
- if ( pending )
- {
- setState( Deferred.CANCELLED_STATE );
-
- notify( cancelCallbacks.concat( alwaysCallbacks ), reason );
- releaseCallbacks();
- }
-
- return this;
- }
-
- // ========================================
- // Protected methods
- // ========================================
-
- /**
- * Set the state for this Deferred.
- *
- * @see #pending
- * @see #succeeded
- * @see #failed
- * @see #cancelled
- */
- protected function setState( value:String ):void
- {
- if ( value != state )
- {
- state = value;
- dispatchEvent( new Event( STATE_CHANGED ) );
- }
- }
-
- /**
- * Notify the specified callbacks, optionally passing the a reference to this Deferred and the specified value.
- */
- protected function notify( callbacks:Array, value:* ):void
- {
- for each ( var callback:Function in callbacks )
- {
- switch ( callback.length )
- {
- case 2:
- callback( promise, value );
- break;
-
- case 1:
- callback( value );
- break;
-
- default:
- callback();
- break;
- }
- }
- }
-
- /**
- * Release references to all callbacks registered with this Deferred.
- */
- protected function releaseCallbacks():void
- {
- resultCallbacks = [];
- errorCallbacks = [];
- progressCallbacks = [];
- cancelCallbacks = [];
- alwaysCallbacks = [];
- }
- }
-}
View
297 src/com/codecatalyst/util/promise/Promise.as
@@ -1,297 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2011 CodeCatalyst, LLC - http://www.codecatalyst.com/
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-////////////////////////////////////////////////////////////////////////////////
-
-package com.codecatalyst.util.promise
-{
- import flash.events.Event;
- import flash.events.EventDispatcher;
-
- /**
- * Promise.
- *
- * An object that acts as a proxy for observing deferred result, fault or progress state from a synchronous or asynchronous operation.
- *
- * Inspired by jQuery's Promise implementation.
- *
- * @author John Yanarella
- */
- public class Promise extends EventDispatcher
- {
- // ========================================
- // Public properties
- // ========================================
-
- [Bindable( "stateChanged" )]
- /**
- * Indicates this Promise has not yet been fulfilled.
- */
- public function get unfulfilled():Boolean
- {
- return deferred.pending;
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Indicates this Promise has been fulfilled.
- */
- public function get fulfilled():Boolean
- {
- return deferred.succeeded;
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Indicates this Promise has failed.
- */
- public function get failed():Boolean
- {
- return deferred.failed;
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Indicates this Promise has been cancelled.
- */
- public function get cancelled():Boolean
- {
- return deferred.cancelled;
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Progress supplied when this Promise was updated.
- */
- public function get progress():*
- {
- return deferred.progress;
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Result supplied when this Promise was fulfilled.
- */
- public function get result():*
- {
- return deferred.result;
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Error supplied when this Promise failed.
- */
- public function get error():*
- {
- return deferred.error;
- }
-
- [Bindable( "stateChanged" )]
- /**
- * Reason supplied when this Promise failed.
- */
- public function get reason():*
- {
- return deferred.reason;
- }
-
- // ========================================
- // Protected properties
- // ========================================
-
- /**
- * Deferred operation for which this is a Promise.
- */
- protected var deferred:Deferred = null;
-
- // ========================================
- // Constructor
- // ========================================
-
- /**
- * Constructor.
- */
- public function Promise( deferred:Deferred )
- {
- super();
-
- this.deferred = deferred;
-
- deferred.addEventListener( Deferred.STATE_CHANGED, deferred_stateChangeHandler, false, 0, true );
- }
-
- // ========================================
- // Public static methods
- // ========================================
-
- /**
- * Utility method to create a new Promise based on one or more Promises (i.e. parallel chaining).
- *
- * NOTE: Result and progress handlers added to this new Promise will be passed an Array of aggregated result or progress values.
- */
- public static function when( ...promises ):Promise
- {
- var deferred:Deferred = new Deferred();
-
- // Special handling for when an Array of Promises is specified instead of variable numbe of Promise arguments.
- if ( ( promises.length == 1 ) && ( promises[ 0 ] is Array ) )
- promises = promises[ 0 ];
-
- // Ensure the promises Array is populated with Promises.
- var parameterCount:int = promises.length;
- for ( var parameterIndex:int = 0; parameterIndex < parameterCount; parameterIndex++ )
- {
- var parameter:* = promises[ parameterIndex ];
-
- switch ( parameter.constructor )
- {
- case Promise:
- break;
-
- case Deferred:
- // Replace the promises Array element with the associated Promise for the specified Deferred value.
- promises[ parameterIndex ] = parameter.promise;
- break;
-
- default:
- // Create a new Deferred resolved with the specified parameter value, and replace the promises Array element with the associated Promise.
- promises[ parameterIndex ] = new Deferred().resolve( parameter ).promise;
- break;
- }
- }
-
- var pendingPromiseCount:int = promises.length;
-
- var progressValues:Array = new Array( pendingPromiseCount );
- var resultValues:Array = new Array( pendingPromiseCount );
-
- for each ( var promise:Promise in promises )
- {
- promise
- .then(
- function ( promise:Promise, result:* ):void
- {
- resultValues[ promises.indexOf( promise ) ] = result;
-
- pendingPromiseCount--;
- if ( pendingPromiseCount == 0 )
- deferred.resolve( resultValues );
- },
- function ( error:* ):void
- {
- deferred.reject( error );
- },
- function ( promise:Promise, update:* ):void
- {
- progressValues[ promises.indexOf( promise ) ] = update;
-
- deferred.update( progressValues );
- },
- function ( reason:* ):void
- {
- deferred.cancel( reason );
- }
- );
- }
-
- return deferred.promise;
- }
-
- // ========================================
- // Public methods
- // ========================================
-
- /**
- * Register callbacks to be called when this Promise is resolved or rejected.
- */
- public function then( resultCallback:Function, errorCallback:Function = null, progressCallback:Function = null, cancelCallback:Function = null ):Promise
- {
- return deferred.then( resultCallback, errorCallback, progressCallback, cancelCallback ).promise;
- }
-
- /**
- * Registers a callback to be called when this Promise is either resolved or rejected.
- */
- public function always( alwaysCallback:Function ):Promise
- {
- return deferred.always( alwaysCallback ).promise;
- }
-
- /**
- * Utility method to filter and/or chain Deferreds.
- */
- public function pipe( resultCallback:Function, errorCallback:Function = null ):Promise
- {
- return deferred.pipe( resultCallback, errorCallback );
- }
-
- /**
- * Registers a callback to be called when this Promise is updated.
- */
- public function onProgress( progressCallback:Function ):Promise
- {
- return deferred.onProgress( progressCallback ).promise;
- }
-
- /**
- * Registers a callback to be called when this Promise is resolved.
- */
- public function onResult( resultCallback:Function ):Promise
- {
- return deferred.onResult( resultCallback ).promise;
- }
-
- /**
- * Registers a callback to be called when this Promise is rejected.
- */
- public function onError( errorCallback:Function ):Promise
- {
- return deferred.onError( errorCallback ).promise;
- }
-
- /**
- * Registers a callback to be called when this Promise is cancelled.
- */
- public function onCancel( cancelCallback:Function ):Promise
- {
- return deferred.onCancel( cancelCallback ).promise;
- }
-
- /**
- * Cancel this Promise.
- */
- public function cancel( reason:* = null ):void
- {
- deferred.cancel( reason );
- }
-
- // ========================================
- // Protected methods
- // ========================================
-
- /**
- * Handle and redispatch state change notifications from the Deferred operation.
- */
- protected function deferred_stateChangeHandler( event:Event ):void
- {
- dispatchEvent( event.clone() );
- }
- }
-}
View
106 src/com/codecatalyst/util/promise/PromiseUtil.as
@@ -1,106 +0,0 @@
-package com.codecatalyst.util.promise
-{
- import com.codecatalyst.util.PropertyUtil;
-
- import flash.events.Event;
- import flash.events.IEventDispatcher;
-
- /**
- * Utility methods related to Promises and adapting Flash and ActionScript asynchronous operations for use with Promises.
- *
- * @see com.codecatalyst.util.AsyncTokenUtil#createPromise()
- *
- * @author John Yanarella
- */
- public class PromiseUtil
- {
- /**
- * Creates a Promise that adapts an asynchronous operation that uses Event based notification, given
- * the event dispatcher, a single result event type, an Array of potential fault types, and an optional progress type.
- *
- * NOTE: Event dispatchers that dispatch Events corresponding to multiple concurrent asynchronous operations cannot be adapted with this approach unless
- * there is a 'token' property accessible via the Event or Event target which can be used to correlate an operation with its Events.
- * In this case, use the optional eventTokenProperty and eventTokenPropertyPath parameters to specify this token and its path (in dot notation) relative to the Events.
- *
- * Promise callbacks will be called with the corresponding Event; consider using Promise's pipe() method to process the Event into result or fault values.
- * @see com.codecatalyst.util.promise.Promise#pipe()
- *
- * NOTE: It is critical to specify the result event type and all possible fault event types to avoid introducing memory leaks.
- */
- public static function listen( dispatcher:IEventDispatcher, resultEventType:String, faultEventTypes:Array, progressEventType:String = null, progressEventProperty:String = null, useCapture:Boolean = false, priority:int = 0, eventTokenPropertyPath:String = null, expectedTokenValue:* = null ):Promise
- {
- var deferred:Deferred = new Deferred();
-
- // Check for a correlating token value, if applicable.
- function checkToken( event:Event ):Boolean
- {
- if ( eventTokenPropertyPath != null )
- {
- var token:* = PropertyUtil.getObjectPropertyValue( event, eventTokenPropertyPath );
-
- return ( token == expectedTokenValue );
- }
-
- return true;
- }
-
- // Result event handling closure.
- function resolve( event:Event ):void
- {
- if ( checkToken() )
- {
- deferred.resolve( event );
- release();
- }
- }
-
- // Fault event handling closure.
- function reject( event:Event ):void
- {
- if ( checkToken() )
- {
- deferred.reject( event );
- release();
- }
- }
-
- // Progress event handling closure.
- function update( event:Event ):void
- {
- if ( checkToken() )
- {
- deferred.update( event[ progressEventProperty ] );
- }
- }
-
- // Clean-up logic - required to avoid memory leaks.
- function release():void
- {
- dispatcher.removeEventListener( resultEventType, resolve, useCapture );
-
- for each ( var faultEventType:String in faultEventTypes )
- {
- dispatcher.removeEventListener( faultEventType, reject, useCapture );
- }
-
- if ( ( progressEventType != null ) && ( progressEventProperty != null ) )
- dispatcher.removeEventListener( progressEventType, update, useCapture );
- }
-
- // Listen for result event.
- dispatcher.addEventListener( resultEventType, resolve, useCapture, priority );
-
- // Listen for fault event.
- for each ( var faultEventType:String in faultEventTypes )
- {
- dispatcher.addEventListener( faultEventType, reject, useCapture, priority );
- }
-
- // Listen for progress event, if applicable.
- if ( ( progressEventType != null ) && ( progressEventProperty != null ) )
- dispatcher.addEventListener( progressEventType, update, useCapture, priority );
-
- return deferred.promise;
- }
- }
-}

0 comments on commit d46d6cf

Please sign in to comment.