Harbs, I think you are referring to asynchronous callback chaining, which,
IMO, does not replace addEventListener per-se.  IOW, it is not the same as:

class SomeClass {
  public var oneAndOnlyOneCallBack:Function;
  public function doSomethingAfterSettingCallback():void;
}

Instead, I think you are asking about a different way of implementing the
AsyncToken API from the regular Flex SDK's HTTPService/RemoteObject which
is roughly:

class AsyncToken {
  var responders:Array
}

class SomeClass {
  public function doSomethingAndGetAsyncToken():AsyncToken;
}


If, for example, you change AsyncToken to have a success() method that
returns the AsyncToken, then you can enable a chaining API.

class AsyncToken {
  public function success(callback:Function):AsyncToken
  {
    ...
    return this;
  }
}


That said, it is important to remember to make properties and events a
priority in Flex APIs.  JavaScript does not have a declarative language
like MXML, and MXML is all about properties and events and less about
functions/methods (no good way to declaratively call a function/method in
MXML).

So, IMO, it is fine to offer alternative APIs for popular patterns, but
Flex/FlexJS is going to show the world that declarative is even better.
And that's why I was playing around with making the FlexJS HTTPService a
Strand for Beads.  Besides the Flex pattern of success/failure events:

<js:HTTPService success="doSomething()" failure="reportFailure()" />

with beads it is possible to declare handlers that expect something from
the strand:

<js:HTTPService>
  <js:strand>
    <local:MySuccessBead />
    <local:MyFailureBead />
    <thirdparty:SomeOtherSucccessBead />
  </js?strand>

That is also chaining, but all declarative.

So, IMO, most things that are synchronous should dispatch an event since
it provides more flexibility than a single callback, but asynchronous
stuff can support chaining APIs if you want.  But please make sure there
is some declarative API as eel.

Thanks,
-Alex

On 7/5/16, 7:08 AM, "Harbs" <harbs.li...@gmail.com> wrote:

>OK. I’ll leave it an EventDispatcher. But, should we try to emulate the
>callback paradigm in addition?
>
>On Jul 5, 2016, at 3:07 PM, Josh Tynjala <joshtynj...@gmail.com> wrote:
>
>> There have been multiple cases where a developer decided to use
>>callbacks
>> instead of events in their API because they felt that no one would ever
>> need multiple listeners, and I ended up actually needing them. The
>> workarounds required can be ugly. Having been there, I try to avoid
>>making
>> assumptions like that in my own code.
>> 
>> Just my personal experience.
>> 
>> - Josh
>> On Jul 5, 2016 3:25 AM, "Harbs" <harbs.li...@gmail.com> wrote:
>> 
>>> I’d like to start a discussion on what I did here.
>>> 
>>> There is a pretty popular pattern in Javascript which allows for
>>>chaining
>>> of callbacks. Instead of lots of addEventListeners and such, you would
>>>do
>>> myClass.doSomething().success(handleSuccess).error(handleError). It’s
>>> currently giving the class object to the handler, but it could take an
>>> event object instead. I’m not sure what makes more sense.
>>> 
>>> You can also specify things like myClass.onError = handleError.
>>> 
>>> This approach works very well when there’s a single object which needs
>>>the
>>> callbacks. For those types of situations, EventDispatcher is not really
>>> necessary at all. I’m thinking of removing the dependency on
>>> EventDispatcher completely for URLLoader and related classes. Requiring
>>> clients to call add and removeEventListeners is cumbersome and
>>>error-prone.
>>> 
>>> Thoughts?
>>> 
>>> Harbs
>>> 
>>> On Jul 5, 2016, at 1:09 PM, ha...@apache.org wrote:
>>> 
>>>> Repository: flex-asjs
>>>> Updated Branches:
>>>> refs/heads/develop cc22300be -> 298d2041f
>>>> 
>>>> 
>>>> Added callbacks
>>>> 
>>>> 
>>>> Project: http://git-wip-us.apache.org/repos/asf/flex-asjs/repo
>>>> Commit: 
>>>>http://git-wip-us.apache.org/repos/asf/flex-asjs/commit/298d2041
>>>> Tree: http://git-wip-us.apache.org/repos/asf/flex-asjs/tree/298d2041
>>>> Diff: http://git-wip-us.apache.org/repos/asf/flex-asjs/diff/298d2041
>>>> 
>>>> Branch: refs/heads/develop
>>>> Commit: 298d2041ff2c02c203764ed22fb11e131e4b092e
>>>> Parents: cc22300
>>>> Author: Harbs <ha...@in-tools.com>
>>>> Authored: Tue Jul 5 13:09:05 2016 +0300
>>>> Committer: Harbs <ha...@in-tools.com>
>>>> Committed: Tue Jul 5 13:09:05 2016 +0300
>>>> 
>>>> ----------------------------------------------------------------------
>>>> .../flex/org/apache/flex/net/URLBinaryLoader.as | 37 +++++++--
>>>> .../main/flex/org/apache/flex/net/URLLoader.as  | 78
>>>>++++++++++++++++++
>>>> .../main/flex/org/apache/flex/net/URLStream.as  | 86
>>>>+++++++++++++++++++-
>>>> 3 files changed, 191 insertions(+), 10 deletions(-)
>>>> ----------------------------------------------------------------------
>>>> 
>>>> 
>>>> 
>>> 
>>>http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/298d2041/framework
>>>s/projects/Network/src/main/flex/org/apache/flex/net/URLBinaryLoader.as
>>>> ----------------------------------------------------------------------
>>>> diff --git
>>> 
>>>a/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLBinar
>>>yLoader.as
>>> 
>>>b/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLBinar
>>>yLoader.as
>>>> index 2dfc490..ff9121b 100644
>>>> ---
>>> 
>>>a/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLBinar
>>>yLoader.as
>>>> +++
>>> 
>>>b/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLBinar
>>>yLoader.as
>>>> @@ -20,7 +20,6 @@ package org.apache.flex.net
>>>> {
>>>> 
>>>>    import org.apache.flex.events.Event;
>>>> -    import org.apache.flex.events.EventDispatcher;
>>>>    import org.apache.flex.events.ProgressEvent;
>>>>    import org.apache.flex.utils.BinaryData;
>>>> 
>>>> @@ -73,43 +72,63 @@ package org.apache.flex.net
>>>>        {
>>>>            super();
>>>>            stream = new URLStream();
>>>> -            stream.addEventListener(HTTPConstants.COMPLETE,
>>>>onComplete);
>>>> +            stream.addEventListener(HTTPConstants.COMPLETE,
>>> completeHandler);
>>>>        }
>>>> 
>>>> +             /**
>>>> +              *  Makes the URL request.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>>        public function load(request:URLRequest):void
>>>>        {
>>>>            stream.load(request);
>>>>        }
>>>> 
>>>> +             /**
>>>> +              *  Cancels the URL request
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>>        public function close():void
>>>>        {
>>>>            stream.close();
>>>> +                     //TODO do we need a callback for camceling?
>>>>        }
>>>> 
>>>> -        private function redirectEvent(event:Event):void
>>>> -        {
>>>> -            dispatchEvent(event);
>>>> -        }
>>>> -
>>>> -        private function onComplete(event:Event):void
>>>> +        private function completeHandler(event:Event):void
>>>>        {
>>>>            data = stream.response;
>>>>            if (data)
>>>>            {
>>>>                dispatchEvent(event);
>>>> +                             if(onComplete)
>>>> +                                     onComplete(this);
>>>> +
>>>>            }
>>>>            else
>>>>            {
>>>>                // TODO dipatch error event?
>>>>                dispatchEvent(new Event(HTTPConstants.IO_ERROR));
>>>> +                             if(onError)
>>>> +                                     onError(this);
>>>>            }
>>>> +                     cleanupCallbacks();
>>>>        }
>>>> 
>>>> -        private function onProgress(event:ProgressEvent):void
>>>> +        private function progressHandler(event:ProgressEvent):void
>>>>        {
>>>>            this.bytesLoaded = event.current
>>>>            this.bytesTotal = event.total;
>>>>            dispatchEvent(event);
>>>> +                     if(onProgress)
>>>> +                             onProgress(this);
>>>>        }
>>>>    }
>>>> }
>>>> 
>>>> 
>>> 
>>>http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/298d2041/framework
>>>s/projects/Network/src/main/flex/org/apache/flex/net/URLLoader.as
>>>> ----------------------------------------------------------------------
>>>> diff --git
>>> 
>>>a/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLLoade
>>>r.as
>>> 
>>>b/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLLoade
>>>r.as
>>>> index 809e120..102f525 100644
>>>> ---
>>> 
>>>a/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLLoade
>>>r.as
>>>> +++
>>> 
>>>b/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLLoade
>>>r.as
>>>> @@ -86,5 +86,83 @@ package org.apache.flex.net
>>>>              {
>>>>                      throw new Error("URLLoader should not be
>>> instantiated. Use a derived class instead.")
>>>>              }
>>>> +
>>>> +             protected function cleanupCallbacks():void
>>>> +             {
>>>> +                     onComplete = null;
>>>> +                     onError = null;
>>>> +                     onProgress = null;
>>>> +             }
>>>> +             /**
>>>> +              *  Callback for complete event.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>> +             public var onComplete:Function;
>>>> +
>>>> +             /**
>>>> +              *  Callback for error event.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>> +             public var onError:Function;
>>>> +
>>>> +             /**
>>>> +              *  Callback for progress event.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>> +             public var onProgress:Function;
>>>> +
>>>> +             /**
>>>> +              *  Convenience function for complete event to allow
>>> chaining.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>> +             public function complete(callback:Function):URLLoader
>>>> +             {
>>>> +                     onComplete = callback;
>>>> +                     return this;
>>>> +             }
>>>> +
>>>> +             /**
>>>> +              *  Convenience function for error event to allow
>>>>chaining.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>> +             public function error(callback:Function):URLLoader
>>>> +             {
>>>> +                     onError = callback;
>>>> +                     return this;
>>>> +             }
>>>> +
>>>> +             /**
>>>> +              *  Convenience function for progress event to allow
>>> chaining.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>> +             public function progress(callback:Function):URLLoader
>>>> +             {
>>>> +                     onProgress = callback;
>>>> +                     return this;
>>>> +             }
>>>>      }
>>>> }
>>>> \ No newline at end of file
>>>> 
>>>> 
>>> 
>>>http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/298d2041/framework
>>>s/projects/Network/src/main/flex/org/apache/flex/net/URLStream.as
>>>> ----------------------------------------------------------------------
>>>> diff --git
>>> 
>>>a/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLStrea
>>>m.as
>>> 
>>>b/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLStrea
>>>m.as
>>>> index 7b5ff89..e2b1654 100644
>>>> ---
>>> 
>>>a/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLStrea
>>>m.as
>>>> +++
>>> 
>>>b/frameworks/projects/Network/src/main/flex/org/apache/flex/net/URLStrea
>>>m.as
>>>> @@ -107,6 +107,9 @@ package org.apache.flex.net
>>>>        protected function
>>>>flash_complete(event:flash.events.Event):void
>>>>        {
>>>>            dispatchEvent(new
>>> org.apache.flex.events.Event(HTTPConstants.COMPLETE));
>>>> +                     if(onComplete)
>>>> +                             onComplete();
>>>> +                     cleanupCallbacks();
>>>>        }
>>>>        COMPILE::SWF
>>>>        protected function
>>> flash_progress(event:flash.events.ProgressEvent):void
>>>> @@ -129,6 +132,9 @@ package org.apache.flex.net
>>>>            if (xhr.readyState == 4 && xhr.status == 200)
>>>>            {
>>>>                dispatchEvent(new
>>> org.apache.flex.events.Event(HTTPConstants.COMPLETE));
>>>> +                             if(onComplete)
>>>> +                                     onComplete();
>>>> +                             cleanupHandlers();
>>>>            }else if (xhr.readyState==4&&xhr.status==404){
>>>>                //                    dispatchEvent(new
>>> IOErrorEvent(IOErrorEvent.IO_ERROR));
>>>>            }
>>>> @@ -146,9 +152,87 @@ package org.apache.flex.net
>>>>            }
>>>> 
>>>>            //TODO send an event that it's been aborted
>>>> +
>>>> +                     cleanupCallbacks();
>>>> +
>>>>        }
>>>> +             private function cleanupCallbacks():void
>>>> +             {
>>>> +                     onComplete = null;
>>>> +                     onError = null;
>>>> +                     onProgress = null;
>>>> +             }
>>>> +             /**
>>>> +              *  Callback for complete event.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>>        public var onComplete:Function;
>>>> +
>>>> +             /**
>>>> +              *  Callback for error event.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>>        public var onError:Function;
>>>> -    }
>>>> +
>>>> +             /**
>>>> +              *  Callback for progress event.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>> +             public var onProgress:Function;
>>>> +
>>>> +             /**
>>>> +              *  Convenience function for complete event to allow
>>> chaining.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>> +             public function
>>> complete(callback:Function):org.apache.flex.net.URLStream
>>>> +             {
>>>> +                     onComplete = callback;
>>>> +                     return this;
>>>> +             }
>>>> +
>>>> +             /**
>>>> +              *  Convenience function for error event to allow
>>>>chaining.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>> +             public function
>>> error(callback:Function):org.apache.flex.net.URLStream
>>>> +             {
>>>> +                     onError = callback;
>>>> +                     return this;
>>>> +             }
>>>> +
>>>> +             /**
>>>> +              *  Convenience function for progress event to allow
>>> chaining.
>>>> +              *
>>>> +              *  @langversion 3.0
>>>> +              *  @playerversion Flash 10.2
>>>> +              *  @playerversion AIR 2.6
>>>> +              *  @productversion FlexJS 0.7.0
>>>> +              */
>>>> +             public function
>>> progress(callback:Function):org.apache.flex.net.URLStream
>>>> +             {
>>>> +                     onProgress = callback;
>>>> +                     return this;
>>>> +             }
>>>> +}
>>>> }
>>>> 
>>>> 
>>> 
>>> 
>

Reply via email to