CC-Archived / promise-as3

Promises/A+ compliant implementation in ActionScript 3.0
167 stars 52 forks source link

Registration of Promise `Adaptors` #20

Open ThomasBurleson opened 11 years ago

ThomasBurleson commented 11 years ago

Promise.when() internally supports a registry of adapter functions that can be registered to intercept the when() call and deliver a promise instance. Adapter functions are registered via the static method Promise::registerAdapter(). And custom adapter classes can easily register their own static adapt() function to support interception of custom data types.

Promise-AS3 current has an com.codecatalyst.promise.adapters package for all custom adapters classes. Currently developers are required to manually register their customer Adapter adapt() functions using Promise.registerAdapter().

Attempting to use class-level inititializers to autoregister will fail unless the targeted class is explicitly used someplace within the codebase. Since adapters are implicitly used to intercept (and adapt) Promise.when() calls, this means that most adapter classes will NEVER be explicityly used... so static initialization for auto-registration will not work.

Even worse, if the developer forgets to manually register an adapter (eg. AsyncTokenAdapter), then the compiler will probably not link the class definition into the bytecode (unless that class is reference someplace within the bytecode).

We should identify an elegant solution to allow auto-registration of adapter functions/classes.

Perhaps a global registerAdapters() function could be used.

package com.codecatalyst.promise.adapters
{
    import com.codecatalyst.promise.Promise;

    /**
     * Global auto-registration function that
     * centralizes registration of promise.adapters <xxx>Adapter classes
     *
     * Other custom adapters could still be manually registered directly using 
     * Promise::registerAdapter()...
     */
    public function registerAdapters():void {

        Promise.registerAdapter( AsyncTokenAdapter.adapt );
        Promise.registerAdapter( DispatcherAdapter.adapt );
        Promise.registerAdapter( URLLoaderAdapter.adapt  );

    }
}

Then the Promise::when() function could be slightly modified to simply run the registration function.

package com.codecatalyst.promise
{
    import com.codecatalyst.promise.adapters.registration;

    /**
     * Promises represent a future value; i.e., a value that may not yet be available.
     */
    public class Promise
    {
        public static function when( value:* ):Promise
        {
            registerAdpaters();

            for each ( var adapt:Function in adapters )
            {
                const promise:Promise = adapt( value ) as Promise;
                if ( promise )
                    return promise;
            }

            const deferred:Deferred = new Deferred();
            deferred.resolve( value );
            return deferred.promise;
        }    

        /**
        * Run (1x) the registerAdapters() global registration process
        */
        private static function autoRegister():void {
            if ( !_registered ) {
                registerAdpaters();
                _registered = true;
            }
        }

        private static var _registered : Boolean;
    }
}