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; >>>> + } >>>> +} >>>> } >>>> >>>> >>> >>> >