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" <[email protected]> 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 <[email protected]> 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" <[email protected]> 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, [email protected] 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 <[email protected]>
>>>> Authored: Tue Jul 5 13:09:05 2016 +0300
>>>> Committer: Harbs <[email protected]>
>>>> 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;
>>>> + }
>>>> +}
>>>> }
>>>>
>>>>
>>>
>>>
>