You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@royale.apache.org by Harbs <ha...@gmail.com> on 2019/06/04 12:03:07 UTC
Re: [royale-asjs] branch develop updated: Added Async tasks
I finally got fed up enough with Promises et. al. that I broke down and wrote some Async classes which (IMO) are much easier to use.
AsyncTask needs to be subclassed. Here’s an implementation that I’m using in my app. If I find some time, I might create some HTTP tasks. I someone who’s better at docs than me wants to write something, that would be great. ;-)
package com.printui.utils
{
import com.printui.model.vos.FontVO;
import com.printui.model.proxies.FontProxy;
public class LoadFontTask extends AsyncTask
{
public function LoadFontTask(font:FontVO)
{
super();
this.font = font;
}
private var font:FontVO;
override public function run(data:Object = null):void{
var fp:FontProxy = ApplicationFacade.getInstance().retrieveProxy(FontProxy.NAME) as FontProxy;
fp.loadNow(font,fontLoadDone);
}
private function fontLoadDone():void{
if(font.embedded){
complete();
} else {
fail();
}
}
}
}
I’m using it like so:
public function embedFonts(callback:Function):void{
if(fontsEmbedded()){
callback();
} else {
var tasks:Array = [];
var font:FontVO = getAppliedFont();
if(!font.embedded){
tasks.push(new LoadFontTask(font));
}
font = getBulletFont();
if(font && !font.embedded){
tasks.push(new LoadFontTask(font));
}
var task:CompoundAsyncTask = new CompoundAsyncTask(tasks);
task.done(function(task:AsyncTask):void{
if(task.status == "complete"){
// we're good
callback();
} else {
// status is "failed" -- not sure what to do...
}
});
task.run();
}
}
> On Jun 4, 2019, at 2:55 PM, harbs@apache.org wrote:
>
> This is an automated email from the ASF dual-hosted git repository.
>
> harbs pushed a commit to branch develop
> in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
>
>
> The following commit(s) were added to refs/heads/develop by this push:
> new edb052c Added Async tasks
> edb052c is described below
>
> commit edb052cbf2fb1b9db276dff6e4a94ce0a7679f00
> Author: Harbs <ha...@in-tools.com>
> AuthorDate: Tue Jun 4 14:55:00 2019 +0300
>
> Added Async tasks
> ---
> .../CoreJS/src/main/config/compile-js-config.xml | 1 +
> .../Core/src/main/config/compile-swf-config.xml | 1 +
> .../Core/src/main/resources/basic-manifest.xml | 3 +
> .../projects/Core/src/main/royale/CoreClasses.as | 3 +
> .../royale/org/apache/royale/utils/ObjectMap.as | 12 ++
> .../org/apache/royale/utils/async/AsyncTask.as | 180 +++++++++++++++++++++
> .../apache/royale/utils/async/CompoundAsyncTask.as | 135 ++++++++++++++++
> .../royale/utils/async/SequentialAsyncTask.as | 77 +++++++++
> 8 files changed, 412 insertions(+)
>
> diff --git a/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml b/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml
> index bdc495e..e912e57 100644
> --- a/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml
> +++ b/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml
> @@ -71,6 +71,7 @@
> </source-path>
>
> <warn-no-constructor>false</warn-no-constructor>
> + <allow-abstract-classes>true</allow-abstract-classes>
>
> <!-- Use of the instanceof operator. -->
> <warn-instance-of-changes>false</warn-instance-of-changes>
> diff --git a/frameworks/projects/Core/src/main/config/compile-swf-config.xml b/frameworks/projects/Core/src/main/config/compile-swf-config.xml
> index ecd4c77..265d4d8 100644
> --- a/frameworks/projects/Core/src/main/config/compile-swf-config.xml
> +++ b/frameworks/projects/Core/src/main/config/compile-swf-config.xml
> @@ -75,6 +75,7 @@
> </source-path>
>
> <warn-no-constructor>false</warn-no-constructor>
> + <allow-abstract-classes>true</allow-abstract-classes>
>
> <!-- Use of the instanceof operator. -->
> <warn-instance-of-changes>false</warn-instance-of-changes>
> diff --git a/frameworks/projects/Core/src/main/resources/basic-manifest.xml b/frameworks/projects/Core/src/main/resources/basic-manifest.xml
> index ae4b7f7..f40d2e4 100644
> --- a/frameworks/projects/Core/src/main/resources/basic-manifest.xml
> +++ b/frameworks/projects/Core/src/main/resources/basic-manifest.xml
> @@ -52,4 +52,7 @@
> <component id="StyleChangeNotifier" class="org.apache.royale.core.StyleChangeNotifier"/>
>
> <component id="State" class="org.apache.royale.states.State"/>
> +
> + <component id="CompoundAsyncTask" class="org.apache.royale.utils.CompoundAsyncTask">
> + <component id="SequentialAsyncTask" class="org.apache.royale.utils.SequentialAsyncTask">
> </componentPackage>
> diff --git a/frameworks/projects/Core/src/main/royale/CoreClasses.as b/frameworks/projects/Core/src/main/royale/CoreClasses.as
> index 678df00..cdd9b25 100644
> --- a/frameworks/projects/Core/src/main/royale/CoreClasses.as
> +++ b/frameworks/projects/Core/src/main/royale/CoreClasses.as
> @@ -308,6 +308,9 @@ internal class CoreClasses
> import org.apache.royale.utils.date.addSeconds; addSeconds;
> import org.apache.royale.utils.date.addYears; addYears;
>
> + import org.apache.royale.utils.async.CompoundAsyncTask; CompoundAsyncTask;
> + import org.apache.royale.utils.async.SequentialAsyncTask; SequentialAsyncTask;
> +
> import org.apache.royale.utils.css.addDynamicSelector; addDynamicSelector;
>
> COMPILE::JS
> diff --git a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as
> index d3bd5bc..836b76e 100644
> --- a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as
> +++ b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as
> @@ -157,9 +157,21 @@ package org.apache.royale.utils
>
> COMPILE::JS
> {
> + /**
> + * @royalesuppresspublicvarwarning
> + */
> public var get:Function = objectGet;
> + /**
> + * @royalesuppresspublicvarwarning
> + */
> public var set:Function = objectSet;
> + /**
> + * @royalesuppresspublicvarwarning
> + */
> public var has:Function = objectHas;
> + /**
> + * @royalesuppresspublicvarwarning
> + */
> public var delete:Function = objectDelete;
> }
>
> diff --git a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/AsyncTask.as b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/AsyncTask.as
> new file mode 100644
> index 0000000..44a31ce
> --- /dev/null
> +++ b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/AsyncTask.as
> @@ -0,0 +1,180 @@
> +////////////////////////////////////////////////////////////////////////////////
> +//
> +// Licensed to the Apache Software Foundation (ASF) under one or more
> +// contributor license agreements. See the NOTICE file distributed with
> +// this work for additional information regarding copyright ownership.
> +// The ASF licenses this file to You under the Apache License, Version 2.0
> +// (the "License"); you may not use this file except in compliance with
> +// the License. You may obtain a copy of the License at
> +//
> +// http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing, software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> +// See the License for the specific language governing permissions and
> +// limitations under the License.
> +//
> +////////////////////////////////////////////////////////////////////////////////
> +package org.apache.royale.utils.async
> +{
> + import org.apache.royale.events.EventDispatcher;
> + import org.apache.royale.events.Event;
> +
> + /**
> + * AsyncTask is a base class for AsyncTasks which let the caller know when they are done.
> + * AsyncTask is an OOP replacement for Promises and simple callbacks which allows for
> + * strongly typed async requests with any kind of payload and behavior.
> + * AsyncTask must be subclassed to be used.
> + * The subclass must implement the `run` method to define the behavior when the task is "run".
> + */
> +
> + [Event(name="complete", type="org.apache.royale.events.Event")]
> + [Event(name="failed", type="org.apache.royale.events.Event")]
> + [Event(name="done", type="org.apache.royale.events.Event")]
> + public abstract class AsyncTask extends EventDispatcher
> + {
> + public function AsyncTask()
> + {
> +
> + }
> + public static const INITIALIZED:String = "initialized";
> + public static const PENDING:String = "pending";
> + public static const COMPLETE:String = "complete";
> + public static const CANCELED:String = "canceled";
> + public static const FAILED:String = "failed";
> + /**
> + * Used in compound tasks
> + */
> + public static const MIXED:String = "mixed";
> + protected var _status:String = "initialized";
> + /**
> + * One of: initialized, pending, complete, failed or mixed (for compound tasks)
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.6
> + */
> + public function get status():String
> + {
> + return _status;
> + }
> +
> + /**
> + * completed (and a status of `complete`) means the task completed successfully
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.6
> + */
> + public function get completed():Boolean
> + {
> + return _status == "complete";
> + }
> + public function set completed(value:Boolean):void
> + {
> + _status = "complete";
> + }
> +
> + /**
> + * failed (and a status of `failed`) means the task resolved to a failed state
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.6
> + */
> + public function get failed():Boolean
> + {
> + return _status == "failed";
> + }
> + public function set failed(value:Boolean):void
> + {
> + _status = "failed";
> + }
> + /**
> + * resolves the task as complete
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.6
> + */
> + public function complete():void{
> + _status = "complete";
> + dispatchEvent(new Event("complete"));
> + notifyDone();
> + }
> + /**
> + * Resolves the task as failed
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.6
> + */
> + public function fail():void{
> + _status = "failed";
> + dispatchEvent(new Event("failed"));
> + notifyDone();
> + }
> + protected function notifyDone():void{
> + dispatchEvent(new Event("done"));
> + if(!doneCallbacks){
> + return;
> + }
> + for(var i:int=0;i<doneCallbacks.length;i++){
> + doneCallbacks[i](this);
> + }
> + }
> + private var doneCallbacks:Array;
> +
> + /**
> + * done accepts a callback which is called when the task is resolved.
> + * The callback is resolved whether the task is successfully completed or not.
> + * The properties of the task should be examined in the callback to determine the results.
> + * The `done` event can be listened too as well.
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.6
> + */
> + public function done(callback:Function):AsyncTask{
> + if(!doneCallbacks){
> + doneCallbacks = [];
> + }
> + doneCallbacks.push(callback);
> + return this;
> + }
> + public abstract function run(data:Object=null):void;
> +
> + /**
> + * cancel resolves the task as "canceled"
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.6
> + */
> + public function cancel():void
> + {
> + _status = "canceled";
> + notifyDone();
> + }
> +
> + private var _data:Object;
> + /**
> + * The data of the task
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.6
> + */
> + public function get data():Object
> + {
> + return _data;
> + }
> +
> + public function set data(value:Object):void
> + {
> + _data = value;
> + }
> +
> + }
> +}
> \ No newline at end of file
> diff --git a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/CompoundAsyncTask.as b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/CompoundAsyncTask.as
> new file mode 100644
> index 0000000..3dee5ef
> --- /dev/null
> +++ b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/CompoundAsyncTask.as
> @@ -0,0 +1,135 @@
> +////////////////////////////////////////////////////////////////////////////////
> +//
> +// Licensed to the Apache Software Foundation (ASF) under one or more
> +// contributor license agreements. See the NOTICE file distributed with
> +// this work for additional information regarding copyright ownership.
> +// The ASF licenses this file to You under the Apache License, Version 2.0
> +// (the "License"); you may not use this file except in compliance with
> +// the License. You may obtain a copy of the License at
> +//
> +// http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing, software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> +// See the License for the specific language governing permissions and
> +// limitations under the License.
> +//
> +////////////////////////////////////////////////////////////////////////////////
> +package org.apache.royale.utils.async
> +{
> + import org.apache.royale.events.Event;
> +
> + /**
> + * The CompoundAsyncTask class allows running a number of AsyncTasks in parallel and resolves when they are done.
> + */
> + public class CompoundAsyncTask extends AsyncTask
> + {
> + public function CompoundAsyncTask(tasks:Array=null)
> + {
> + super();
> + if(!tasks){
> + tasks = [];
> + }
> + this.tasks = tasks;
> + completedTasks = [];
> + failedTasks = [];
> + }
> + protected var tasks:Array;
> +
> + private var _failEarly:Boolean;
> + /**
> + * If <code>failEarly</code> is true, the task will fail as soon as the first subtask fails.
> + */
> + public function get failEarly():Boolean
> + {
> + return _failEarly;
> + }
> +
> + public function set failEarly(value:Boolean):void
> + {
> + _failEarly = value;
> + }
> +
> + public function addTask(task:AsyncTask):void{
> + tasks.push(task);
> + }
> +
> + protected var pendingTasks:Array;
> +
> + /**
> + * @royalesuppresspublicvarwarning
> + */
> + public var completedTasks:Array;
> + /**
> + * @royalesuppresspublicvarwarning
> + */
> + public var failedTasks:Array;
> +
> + override public function run(data:Object=null):void
> + {
> + if(_status == "pending"){// don't allow running twice
> + return;
> + }
> + _status = "pending";
> + pendingTasks = [];
> + for(var i:int=0;i<tasks.length;i++){
> + var task:AsyncTask = tasks[i];
> + task.done(handleDone);
> + pendingTasks.push(task);
> + task.run();
> + }
> + }
> + private function handleDone(task:AsyncTask):void
> + {
> + if(_status != "pending")
> + {
> + return;
> + }
> + var idx:int = pendingTasks.indexOf(task);
> + pendingTasks.splice(idx,1);
> + switch(task.status){
> + case "complete":
> + completedTasks.push(task);
> + break;
> + case "failed":
> + failedTasks.push(task);
> + if(failEarly)
> + {
> + while(pendingTasks.length)
> + {
> + var pending:AsyncTask = pendingTasks.pop();
> + pending.cancel();
> + }
> + fail();
> + return;
> + }
> + break;
> + default:// not sure why this would happen
> + throw new Error("Unknown task status");
> + }
> + if(pendingTasks.length == 0)
> + {
> + setFinalStatus();
> + }
> + }
> + protected function setFinalStatus():void
> + {
> + if(failedTasks.length == 0)
> + {
> + complete();
> + }
> + else if(completedTasks.length == 0)
> + {
> + fail();
> + }
> + else
> + {// Some passed and some failed -- Does this make sense?
> + _status = "mixed";
> + dispatchEvent(new Event("failed"));
> + dispatchEvent(new Event("complete"));
> + notifyDone();
> + }
> + }
> + }
> +}
> \ No newline at end of file
> diff --git a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/SequentialAsyncTask.as b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/SequentialAsyncTask.as
> new file mode 100644
> index 0000000..77f2f18
> --- /dev/null
> +++ b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/SequentialAsyncTask.as
> @@ -0,0 +1,77 @@
> +////////////////////////////////////////////////////////////////////////////////
> +//
> +// Licensed to the Apache Software Foundation (ASF) under one or more
> +// contributor license agreements. See the NOTICE file distributed with
> +// this work for additional information regarding copyright ownership.
> +// The ASF licenses this file to You under the Apache License, Version 2.0
> +// (the "License"); you may not use this file except in compliance with
> +// the License. You may obtain a copy of the License at
> +//
> +// http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing, software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> +// See the License for the specific language governing permissions and
> +// limitations under the License.
> +//
> +////////////////////////////////////////////////////////////////////////////////
> +package org.apache.royale.utils.async
> +{
> + /**
> + * The SequentialAsyncTask runs a list of tasks in sequential order.
> + * Each sunsequent task is only run once the previous task is done.
> + * The previous task is used as the argument for the next task's run method.
> + * This enables the chaining of results.
> + */
> + public class SequentialAsyncTask extends CompoundAsyncTask
> + {
> + /**
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.6
> + */
> + public function SequentialAsyncTask(tasks:Array=null)
> + {
> + super(tasks);
> + }
> + override public function run(data:Object=null):void
> + {
> + _status = "pending";
> + pendingTasks = tasks.slice();
> + var task:AsyncTask = pendingTasks.shift();
> + task.done(handleDone);
> + task.run();
> + }
> + private function handleDone(task:AsyncTask):void
> + {
> + if(_status != "pending"){
> + return;
> + }
> + switch(task.status){
> + case "complete":
> + completedTasks.push(task);
> + break;
> + case "failed":
> + failedTasks.push(task);
> + if(failEarly){
> + pendingTasks = [];
> + fail();
> + return;
> + }
> + break;
> + default:// not sure why this would happen
> + throw new Error("Unknown task status");
> +
> + }
> + if(pendingTasks.length){
> + var nextTask:AsyncTask = pendingTasks.shift();
> + nextTask.done(handleDone);
> + nextTask.run(task);
> + } else {
> + setFinalStatus();
> + }
> + }
> + }
> +}
> \ No newline at end of file
>
Re: [royale-asjs] branch develop updated: Added Async tasks
Posted by Piotr Zarzycki <pi...@gmail.com>.
Wow that's super awesome! Thanks for this example!
On Tue, Jun 4, 2019, 2:03 PM Harbs <ha...@gmail.com> wrote:
> I finally got fed up enough with Promises et. al. that I broke down and
> wrote some Async classes which (IMO) are much easier to use.
>
> AsyncTask needs to be subclassed. Here’s an implementation that I’m using
> in my app. If I find some time, I might create some HTTP tasks. I someone
> who’s better at docs than me wants to write something, that would be great.
> ;-)
>
> package com.printui.utils
> {
> import com.printui.model.vos.FontVO;
> import com.printui.model.proxies.FontProxy;
>
> public class LoadFontTask extends AsyncTask
> {
> public function LoadFontTask(font:FontVO)
> {
> super();
> this.font = font;
> }
> private var font:FontVO;
> override public function run(data:Object = null):void{
> var fp:FontProxy =
> ApplicationFacade.getInstance().retrieveProxy(FontProxy.NAME) as FontProxy;
> fp.loadNow(font,fontLoadDone);
> }
> private function fontLoadDone():void{
> if(font.embedded){
> complete();
> } else {
> fail();
> }
> }
> }
> }
>
> I’m using it like so:
>
> public function embedFonts(callback:Function):void{
> if(fontsEmbedded()){
> callback();
> } else {
> var tasks:Array = [];
> var font:FontVO = getAppliedFont();
> if(!font.embedded){
> tasks.push(new LoadFontTask(font));
> }
> font = getBulletFont();
> if(font && !font.embedded){
> tasks.push(new LoadFontTask(font));
> }
> var task:CompoundAsyncTask = new CompoundAsyncTask(tasks);
> task.done(function(task:AsyncTask):void{
> if(task.status == "complete"){
> // we're good
> callback();
> } else {
> // status is "failed" -- not sure what to do...
> }
> });
> task.run();
> }
> }
>
>
> > On Jun 4, 2019, at 2:55 PM, harbs@apache.org wrote:
> >
> > This is an automated email from the ASF dual-hosted git repository.
> >
> > harbs pushed a commit to branch develop
> > in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
> >
> >
> > The following commit(s) were added to refs/heads/develop by this push:
> > new edb052c Added Async tasks
> > edb052c is described below
> >
> > commit edb052cbf2fb1b9db276dff6e4a94ce0a7679f00
> > Author: Harbs <ha...@in-tools.com>
> > AuthorDate: Tue Jun 4 14:55:00 2019 +0300
> >
> > Added Async tasks
> > ---
> > .../CoreJS/src/main/config/compile-js-config.xml | 1 +
> > .../Core/src/main/config/compile-swf-config.xml | 1 +
> > .../Core/src/main/resources/basic-manifest.xml | 3 +
> > .../projects/Core/src/main/royale/CoreClasses.as | 3 +
> > .../royale/org/apache/royale/utils/ObjectMap.as | 12 ++
> > .../org/apache/royale/utils/async/AsyncTask.as | 180
> +++++++++++++++++++++
> > .../apache/royale/utils/async/CompoundAsyncTask.as | 135 ++++++++++++++++
> > .../royale/utils/async/SequentialAsyncTask.as | 77 +++++++++
> > 8 files changed, 412 insertions(+)
> >
> > diff --git
> a/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml
> b/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml
> > index bdc495e..e912e57 100644
> > --- a/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml
> > +++ b/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml
> > @@ -71,6 +71,7 @@
> > </source-path>
> >
> > <warn-no-constructor>false</warn-no-constructor>
> > + <allow-abstract-classes>true</allow-abstract-classes>
> >
> > <!-- Use of the instanceof operator. -->
> > <warn-instance-of-changes>false</warn-instance-of-changes>
> > diff --git
> a/frameworks/projects/Core/src/main/config/compile-swf-config.xml
> b/frameworks/projects/Core/src/main/config/compile-swf-config.xml
> > index ecd4c77..265d4d8 100644
> > --- a/frameworks/projects/Core/src/main/config/compile-swf-config.xml
> > +++ b/frameworks/projects/Core/src/main/config/compile-swf-config.xml
> > @@ -75,6 +75,7 @@
> > </source-path>
> >
> > <warn-no-constructor>false</warn-no-constructor>
> > + <allow-abstract-classes>true</allow-abstract-classes>
> >
> > <!-- Use of the instanceof operator. -->
> > <warn-instance-of-changes>false</warn-instance-of-changes>
> > diff --git
> a/frameworks/projects/Core/src/main/resources/basic-manifest.xml
> b/frameworks/projects/Core/src/main/resources/basic-manifest.xml
> > index ae4b7f7..f40d2e4 100644
> > --- a/frameworks/projects/Core/src/main/resources/basic-manifest.xml
> > +++ b/frameworks/projects/Core/src/main/resources/basic-manifest.xml
> > @@ -52,4 +52,7 @@
> > <component id="StyleChangeNotifier"
> class="org.apache.royale.core.StyleChangeNotifier"/>
> >
> > <component id="State" class="org.apache.royale.states.State"/>
> > +
> > + <component id="CompoundAsyncTask"
> class="org.apache.royale.utils.CompoundAsyncTask">
> > + <component id="SequentialAsyncTask"
> class="org.apache.royale.utils.SequentialAsyncTask">
> > </componentPackage>
> > diff --git a/frameworks/projects/Core/src/main/royale/CoreClasses.as
> b/frameworks/projects/Core/src/main/royale/CoreClasses.as
> > index 678df00..cdd9b25 100644
> > --- a/frameworks/projects/Core/src/main/royale/CoreClasses.as
> > +++ b/frameworks/projects/Core/src/main/royale/CoreClasses.as
> > @@ -308,6 +308,9 @@ internal class CoreClasses
> > import org.apache.royale.utils.date.addSeconds; addSeconds;
> > import org.apache.royale.utils.date.addYears; addYears;
> >
> > + import org.apache.royale.utils.async.CompoundAsyncTask;
> CompoundAsyncTask;
> > + import org.apache.royale.utils.async.SequentialAsyncTask;
> SequentialAsyncTask;
> > +
> > import org.apache.royale.utils.css.addDynamicSelector;
> addDynamicSelector;
> >
> > COMPILE::JS
> > diff --git
> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as
> > index d3bd5bc..836b76e 100644
> > ---
> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as
> > +++
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as
> > @@ -157,9 +157,21 @@ package org.apache.royale.utils
> >
> > COMPILE::JS
> > {
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > public var get:Function = objectGet;
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > public var set:Function = objectSet;
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > public var has:Function = objectHas;
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > public var delete:Function = objectDelete;
> > }
> >
> > diff --git
> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/AsyncTask.as
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/AsyncTask.as
> > new file mode 100644
> > index 0000000..44a31ce
> > --- /dev/null
> > +++
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/AsyncTask.as
> > @@ -0,0 +1,180 @@
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +//
> > +// Licensed to the Apache Software Foundation (ASF) under one or more
> > +// contributor license agreements. See the NOTICE file distributed
> with
> > +// this work for additional information regarding copyright ownership.
> > +// The ASF licenses this file to You under the Apache License, Version
> 2.0
> > +// (the "License"); you may not use this file except in compliance with
> > +// the License. You may obtain a copy of the License at
> > +//
> > +// http://www.apache.org/licenses/LICENSE-2.0
> > +//
> > +// Unless required by applicable law or agreed to in writing, software
> > +// distributed under the License is distributed on an "AS IS" BASIS,
> > +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> > +// See the License for the specific language governing permissions and
> > +// limitations under the License.
> > +//
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +package org.apache.royale.utils.async
> > +{
> > + import org.apache.royale.events.EventDispatcher;
> > + import org.apache.royale.events.Event;
> > +
> > + /**
> > + * AsyncTask is a base class for AsyncTasks which let the caller know
> when they are done.
> > + * AsyncTask is an OOP replacement for Promises and simple callbacks
> which allows for
> > + * strongly typed async requests with any kind of payload and
> behavior.
> > + * AsyncTask must be subclassed to be used.
> > + * The subclass must implement the `run` method to define the
> behavior when the task is "run".
> > + */
> > +
> > + [Event(name="complete", type="org.apache.royale.events.Event")]
> > + [Event(name="failed", type="org.apache.royale.events.Event")]
> > + [Event(name="done", type="org.apache.royale.events.Event")]
> > + public abstract class AsyncTask extends EventDispatcher
> > + {
> > + public function AsyncTask()
> > + {
> > +
> > + }
> > + public static const INITIALIZED:String = "initialized";
> > + public static const PENDING:String = "pending";
> > + public static const COMPLETE:String = "complete";
> > + public static const CANCELED:String = "canceled";
> > + public static const FAILED:String = "failed";
> > + /**
> > + * Used in compound tasks
> > + */
> > + public static const MIXED:String = "mixed";
> > + protected var _status:String = "initialized";
> > + /**
> > + * One of: initialized, pending, complete, failed or mixed (for
> compound tasks)
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function get status():String
> > + {
> > + return _status;
> > + }
> > +
> > + /**
> > + * completed (and a status of `complete`) means the task completed
> successfully
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function get completed():Boolean
> > + {
> > + return _status == "complete";
> > + }
> > + public function set completed(value:Boolean):void
> > + {
> > + _status = "complete";
> > + }
> > +
> > + /**
> > + * failed (and a status of `failed`) means the task resolved to a
> failed state
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function get failed():Boolean
> > + {
> > + return _status == "failed";
> > + }
> > + public function set failed(value:Boolean):void
> > + {
> > + _status = "failed";
> > + }
> > + /**
> > + * resolves the task as complete
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function complete():void{
> > + _status = "complete";
> > + dispatchEvent(new Event("complete"));
> > + notifyDone();
> > + }
> > + /**
> > + * Resolves the task as failed
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function fail():void{
> > + _status = "failed";
> > + dispatchEvent(new Event("failed"));
> > + notifyDone();
> > + }
> > + protected function notifyDone():void{
> > + dispatchEvent(new Event("done"));
> > + if(!doneCallbacks){
> > + return;
> > + }
> > + for(var i:int=0;i<doneCallbacks.length;i++){
> > + doneCallbacks[i](this);
> > + }
> > + }
> > + private var doneCallbacks:Array;
> > +
> > + /**
> > + * done accepts a callback which is called when the task is
> resolved.
> > + * The callback is resolved whether the task is successfully
> completed or not.
> > + * The properties of the task should be examined in the callback to
> determine the results.
> > + * The `done` event can be listened too as well.
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function done(callback:Function):AsyncTask{
> > + if(!doneCallbacks){
> > + doneCallbacks = [];
> > + }
> > + doneCallbacks.push(callback);
> > + return this;
> > + }
> > + public abstract function run(data:Object=null):void;
> > +
> > + /**
> > + * cancel resolves the task as "canceled"
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function cancel():void
> > + {
> > + _status = "canceled";
> > + notifyDone();
> > + }
> > +
> > + private var _data:Object;
> > + /**
> > + * The data of the task
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function get data():Object
> > + {
> > + return _data;
> > + }
> > +
> > + public function set data(value:Object):void
> > + {
> > + _data = value;
> > + }
> > +
> > + }
> > +}
> > \ No newline at end of file
> > diff --git
> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/CompoundAsyncTask.as
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/CompoundAsyncTask.as
> > new file mode 100644
> > index 0000000..3dee5ef
> > --- /dev/null
> > +++
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/CompoundAsyncTask.as
> > @@ -0,0 +1,135 @@
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +//
> > +// Licensed to the Apache Software Foundation (ASF) under one or more
> > +// contributor license agreements. See the NOTICE file distributed
> with
> > +// this work for additional information regarding copyright ownership.
> > +// The ASF licenses this file to You under the Apache License, Version
> 2.0
> > +// (the "License"); you may not use this file except in compliance with
> > +// the License. You may obtain a copy of the License at
> > +//
> > +// http://www.apache.org/licenses/LICENSE-2.0
> > +//
> > +// Unless required by applicable law or agreed to in writing, software
> > +// distributed under the License is distributed on an "AS IS" BASIS,
> > +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> > +// See the License for the specific language governing permissions and
> > +// limitations under the License.
> > +//
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +package org.apache.royale.utils.async
> > +{
> > + import org.apache.royale.events.Event;
> > +
> > + /**
> > + * The CompoundAsyncTask class allows running a number of AsyncTasks
> in parallel and resolves when they are done.
> > + */
> > + public class CompoundAsyncTask extends AsyncTask
> > + {
> > + public function CompoundAsyncTask(tasks:Array=null)
> > + {
> > + super();
> > + if(!tasks){
> > + tasks = [];
> > + }
> > + this.tasks = tasks;
> > + completedTasks = [];
> > + failedTasks = [];
> > + }
> > + protected var tasks:Array;
> > +
> > + private var _failEarly:Boolean;
> > + /**
> > + * If <code>failEarly</code> is true, the task will fail as soon as
> the first subtask fails.
> > + */
> > + public function get failEarly():Boolean
> > + {
> > + return _failEarly;
> > + }
> > +
> > + public function set failEarly(value:Boolean):void
> > + {
> > + _failEarly = value;
> > + }
> > +
> > + public function addTask(task:AsyncTask):void{
> > + tasks.push(task);
> > + }
> > +
> > + protected var pendingTasks:Array;
> > +
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > + public var completedTasks:Array;
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > + public var failedTasks:Array;
> > +
> > + override public function run(data:Object=null):void
> > + {
> > + if(_status == "pending"){// don't allow running twice
> > + return;
> > + }
> > + _status = "pending";
> > + pendingTasks = [];
> > + for(var i:int=0;i<tasks.length;i++){
> > + var task:AsyncTask = tasks[i];
> > + task.done(handleDone);
> > + pendingTasks.push(task);
> > + task.run();
> > + }
> > + }
> > + private function handleDone(task:AsyncTask):void
> > + {
> > + if(_status != "pending")
> > + {
> > + return;
> > + }
> > + var idx:int = pendingTasks.indexOf(task);
> > + pendingTasks.splice(idx,1);
> > + switch(task.status){
> > + case "complete":
> > + completedTasks.push(task);
> > + break;
> > + case "failed":
> > + failedTasks.push(task);
> > + if(failEarly)
> > + {
> > + while(pendingTasks.length)
> > + {
> > + var pending:AsyncTask = pendingTasks.pop();
> > + pending.cancel();
> > + }
> > + fail();
> > + return;
> > + }
> > + break;
> > + default:// not sure why this would happen
> > + throw new Error("Unknown task status");
> > + }
> > + if(pendingTasks.length == 0)
> > + {
> > + setFinalStatus();
> > + }
> > + }
> > + protected function setFinalStatus():void
> > + {
> > + if(failedTasks.length == 0)
> > + {
> > + complete();
> > + }
> > + else if(completedTasks.length == 0)
> > + {
> > + fail();
> > + }
> > + else
> > + {// Some passed and some failed -- Does this make sense?
> > + _status = "mixed";
> > + dispatchEvent(new Event("failed"));
> > + dispatchEvent(new Event("complete"));
> > + notifyDone();
> > + }
> > + }
> > + }
> > +}
> > \ No newline at end of file
> > diff --git
> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/SequentialAsyncTask.as
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/SequentialAsyncTask.as
> > new file mode 100644
> > index 0000000..77f2f18
> > --- /dev/null
> > +++
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/SequentialAsyncTask.as
> > @@ -0,0 +1,77 @@
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +//
> > +// Licensed to the Apache Software Foundation (ASF) under one or more
> > +// contributor license agreements. See the NOTICE file distributed
> with
> > +// this work for additional information regarding copyright ownership.
> > +// The ASF licenses this file to You under the Apache License, Version
> 2.0
> > +// (the "License"); you may not use this file except in compliance with
> > +// the License. You may obtain a copy of the License at
> > +//
> > +// http://www.apache.org/licenses/LICENSE-2.0
> > +//
> > +// Unless required by applicable law or agreed to in writing, software
> > +// distributed under the License is distributed on an "AS IS" BASIS,
> > +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> > +// See the License for the specific language governing permissions and
> > +// limitations under the License.
> > +//
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +package org.apache.royale.utils.async
> > +{
> > + /**
> > + * The SequentialAsyncTask runs a list of tasks in sequential order.
> > + * Each sunsequent task is only run once the previous task is done.
> > + * The previous task is used as the argument for the next task's run
> method.
> > + * This enables the chaining of results.
> > + */
> > + public class SequentialAsyncTask extends CompoundAsyncTask
> > + {
> > + /**
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function SequentialAsyncTask(tasks:Array=null)
> > + {
> > + super(tasks);
> > + }
> > + override public function run(data:Object=null):void
> > + {
> > + _status = "pending";
> > + pendingTasks = tasks.slice();
> > + var task:AsyncTask = pendingTasks.shift();
> > + task.done(handleDone);
> > + task.run();
> > + }
> > + private function handleDone(task:AsyncTask):void
> > + {
> > + if(_status != "pending"){
> > + return;
> > + }
> > + switch(task.status){
> > + case "complete":
> > + completedTasks.push(task);
> > + break;
> > + case "failed":
> > + failedTasks.push(task);
> > + if(failEarly){
> > + pendingTasks = [];
> > + fail();
> > + return;
> > + }
> > + break;
> > + default:// not sure why this would happen
> > + throw new Error("Unknown task status");
> > +
> > + }
> > + if(pendingTasks.length){
> > + var nextTask:AsyncTask = pendingTasks.shift();
> > + nextTask.done(handleDone);
> > + nextTask.run(task);
> > + } else {
> > + setFinalStatus();
> > + }
> > + }
> > + }
> > +}
> > \ No newline at end of file
> >
>
>
Re: [royale-asjs] branch develop updated: Added Async tasks
Posted by Carlos Rovira <ca...@apache.org>.
Hi Harbs,
any of us that are working on Docs now can do this, but I think we need
more explanation about what is all about.
Is important to create a code that works, but is equally important to
explain what is the purpose so we can understand what's the improvement.
And I think this goes for all of us, included me.
Can you explain more about this?
As well give some clues of where s that code located, seems in print, but
nor in Royale?
With all of that then we can plan some docs to expose this.
Thanks! :)
El mar., 4 jun. 2019 a las 14:03, Harbs (<ha...@gmail.com>) escribió:
> I finally got fed up enough with Promises et. al. that I broke down and
> wrote some Async classes which (IMO) are much easier to use.
>
> AsyncTask needs to be subclassed. Here’s an implementation that I’m using
> in my app. If I find some time, I might create some HTTP tasks. I someone
> who’s better at docs than me wants to write something, that would be great.
> ;-)
>
> package com.printui.utils
> {
> import com.printui.model.vos.FontVO;
> import com.printui.model.proxies.FontProxy;
>
> public class LoadFontTask extends AsyncTask
> {
> public function LoadFontTask(font:FontVO)
> {
> super();
> this.font = font;
> }
> private var font:FontVO;
> override public function run(data:Object = null):void{
> var fp:FontProxy =
> ApplicationFacade.getInstance().retrieveProxy(FontProxy.NAME) as FontProxy;
> fp.loadNow(font,fontLoadDone);
> }
> private function fontLoadDone():void{
> if(font.embedded){
> complete();
> } else {
> fail();
> }
> }
> }
> }
>
> I’m using it like so:
>
> public function embedFonts(callback:Function):void{
> if(fontsEmbedded()){
> callback();
> } else {
> var tasks:Array = [];
> var font:FontVO = getAppliedFont();
> if(!font.embedded){
> tasks.push(new LoadFontTask(font));
> }
> font = getBulletFont();
> if(font && !font.embedded){
> tasks.push(new LoadFontTask(font));
> }
> var task:CompoundAsyncTask = new CompoundAsyncTask(tasks);
> task.done(function(task:AsyncTask):void{
> if(task.status == "complete"){
> // we're good
> callback();
> } else {
> // status is "failed" -- not sure what to do...
> }
> });
> task.run();
> }
> }
>
>
> > On Jun 4, 2019, at 2:55 PM, harbs@apache.org wrote:
> >
> > This is an automated email from the ASF dual-hosted git repository.
> >
> > harbs pushed a commit to branch develop
> > in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
> >
> >
> > The following commit(s) were added to refs/heads/develop by this push:
> > new edb052c Added Async tasks
> > edb052c is described below
> >
> > commit edb052cbf2fb1b9db276dff6e4a94ce0a7679f00
> > Author: Harbs <ha...@in-tools.com>
> > AuthorDate: Tue Jun 4 14:55:00 2019 +0300
> >
> > Added Async tasks
> > ---
> > .../CoreJS/src/main/config/compile-js-config.xml | 1 +
> > .../Core/src/main/config/compile-swf-config.xml | 1 +
> > .../Core/src/main/resources/basic-manifest.xml | 3 +
> > .../projects/Core/src/main/royale/CoreClasses.as | 3 +
> > .../royale/org/apache/royale/utils/ObjectMap.as | 12 ++
> > .../org/apache/royale/utils/async/AsyncTask.as | 180
> +++++++++++++++++++++
> > .../apache/royale/utils/async/CompoundAsyncTask.as | 135 ++++++++++++++++
> > .../royale/utils/async/SequentialAsyncTask.as | 77 +++++++++
> > 8 files changed, 412 insertions(+)
> >
> > diff --git
> a/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml
> b/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml
> > index bdc495e..e912e57 100644
> > --- a/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml
> > +++ b/frameworks/js/projects/CoreJS/src/main/config/compile-js-config.xml
> > @@ -71,6 +71,7 @@
> > </source-path>
> >
> > <warn-no-constructor>false</warn-no-constructor>
> > + <allow-abstract-classes>true</allow-abstract-classes>
> >
> > <!-- Use of the instanceof operator. -->
> > <warn-instance-of-changes>false</warn-instance-of-changes>
> > diff --git
> a/frameworks/projects/Core/src/main/config/compile-swf-config.xml
> b/frameworks/projects/Core/src/main/config/compile-swf-config.xml
> > index ecd4c77..265d4d8 100644
> > --- a/frameworks/projects/Core/src/main/config/compile-swf-config.xml
> > +++ b/frameworks/projects/Core/src/main/config/compile-swf-config.xml
> > @@ -75,6 +75,7 @@
> > </source-path>
> >
> > <warn-no-constructor>false</warn-no-constructor>
> > + <allow-abstract-classes>true</allow-abstract-classes>
> >
> > <!-- Use of the instanceof operator. -->
> > <warn-instance-of-changes>false</warn-instance-of-changes>
> > diff --git
> a/frameworks/projects/Core/src/main/resources/basic-manifest.xml
> b/frameworks/projects/Core/src/main/resources/basic-manifest.xml
> > index ae4b7f7..f40d2e4 100644
> > --- a/frameworks/projects/Core/src/main/resources/basic-manifest.xml
> > +++ b/frameworks/projects/Core/src/main/resources/basic-manifest.xml
> > @@ -52,4 +52,7 @@
> > <component id="StyleChangeNotifier"
> class="org.apache.royale.core.StyleChangeNotifier"/>
> >
> > <component id="State" class="org.apache.royale.states.State"/>
> > +
> > + <component id="CompoundAsyncTask"
> class="org.apache.royale.utils.CompoundAsyncTask">
> > + <component id="SequentialAsyncTask"
> class="org.apache.royale.utils.SequentialAsyncTask">
> > </componentPackage>
> > diff --git a/frameworks/projects/Core/src/main/royale/CoreClasses.as
> b/frameworks/projects/Core/src/main/royale/CoreClasses.as
> > index 678df00..cdd9b25 100644
> > --- a/frameworks/projects/Core/src/main/royale/CoreClasses.as
> > +++ b/frameworks/projects/Core/src/main/royale/CoreClasses.as
> > @@ -308,6 +308,9 @@ internal class CoreClasses
> > import org.apache.royale.utils.date.addSeconds; addSeconds;
> > import org.apache.royale.utils.date.addYears; addYears;
> >
> > + import org.apache.royale.utils.async.CompoundAsyncTask;
> CompoundAsyncTask;
> > + import org.apache.royale.utils.async.SequentialAsyncTask;
> SequentialAsyncTask;
> > +
> > import org.apache.royale.utils.css.addDynamicSelector;
> addDynamicSelector;
> >
> > COMPILE::JS
> > diff --git
> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as
> > index d3bd5bc..836b76e 100644
> > ---
> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as
> > +++
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/ObjectMap.as
> > @@ -157,9 +157,21 @@ package org.apache.royale.utils
> >
> > COMPILE::JS
> > {
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > public var get:Function = objectGet;
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > public var set:Function = objectSet;
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > public var has:Function = objectHas;
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > public var delete:Function = objectDelete;
> > }
> >
> > diff --git
> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/AsyncTask.as
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/AsyncTask.as
> > new file mode 100644
> > index 0000000..44a31ce
> > --- /dev/null
> > +++
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/AsyncTask.as
> > @@ -0,0 +1,180 @@
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +//
> > +// Licensed to the Apache Software Foundation (ASF) under one or more
> > +// contributor license agreements. See the NOTICE file distributed
> with
> > +// this work for additional information regarding copyright ownership.
> > +// The ASF licenses this file to You under the Apache License, Version
> 2.0
> > +// (the "License"); you may not use this file except in compliance with
> > +// the License. You may obtain a copy of the License at
> > +//
> > +// http://www.apache.org/licenses/LICENSE-2.0
> > +//
> > +// Unless required by applicable law or agreed to in writing, software
> > +// distributed under the License is distributed on an "AS IS" BASIS,
> > +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> > +// See the License for the specific language governing permissions and
> > +// limitations under the License.
> > +//
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +package org.apache.royale.utils.async
> > +{
> > + import org.apache.royale.events.EventDispatcher;
> > + import org.apache.royale.events.Event;
> > +
> > + /**
> > + * AsyncTask is a base class for AsyncTasks which let the caller know
> when they are done.
> > + * AsyncTask is an OOP replacement for Promises and simple callbacks
> which allows for
> > + * strongly typed async requests with any kind of payload and
> behavior.
> > + * AsyncTask must be subclassed to be used.
> > + * The subclass must implement the `run` method to define the
> behavior when the task is "run".
> > + */
> > +
> > + [Event(name="complete", type="org.apache.royale.events.Event")]
> > + [Event(name="failed", type="org.apache.royale.events.Event")]
> > + [Event(name="done", type="org.apache.royale.events.Event")]
> > + public abstract class AsyncTask extends EventDispatcher
> > + {
> > + public function AsyncTask()
> > + {
> > +
> > + }
> > + public static const INITIALIZED:String = "initialized";
> > + public static const PENDING:String = "pending";
> > + public static const COMPLETE:String = "complete";
> > + public static const CANCELED:String = "canceled";
> > + public static const FAILED:String = "failed";
> > + /**
> > + * Used in compound tasks
> > + */
> > + public static const MIXED:String = "mixed";
> > + protected var _status:String = "initialized";
> > + /**
> > + * One of: initialized, pending, complete, failed or mixed (for
> compound tasks)
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function get status():String
> > + {
> > + return _status;
> > + }
> > +
> > + /**
> > + * completed (and a status of `complete`) means the task completed
> successfully
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function get completed():Boolean
> > + {
> > + return _status == "complete";
> > + }
> > + public function set completed(value:Boolean):void
> > + {
> > + _status = "complete";
> > + }
> > +
> > + /**
> > + * failed (and a status of `failed`) means the task resolved to a
> failed state
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function get failed():Boolean
> > + {
> > + return _status == "failed";
> > + }
> > + public function set failed(value:Boolean):void
> > + {
> > + _status = "failed";
> > + }
> > + /**
> > + * resolves the task as complete
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function complete():void{
> > + _status = "complete";
> > + dispatchEvent(new Event("complete"));
> > + notifyDone();
> > + }
> > + /**
> > + * Resolves the task as failed
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function fail():void{
> > + _status = "failed";
> > + dispatchEvent(new Event("failed"));
> > + notifyDone();
> > + }
> > + protected function notifyDone():void{
> > + dispatchEvent(new Event("done"));
> > + if(!doneCallbacks){
> > + return;
> > + }
> > + for(var i:int=0;i<doneCallbacks.length;i++){
> > + doneCallbacks[i](this);
> > + }
> > + }
> > + private var doneCallbacks:Array;
> > +
> > + /**
> > + * done accepts a callback which is called when the task is
> resolved.
> > + * The callback is resolved whether the task is successfully
> completed or not.
> > + * The properties of the task should be examined in the callback to
> determine the results.
> > + * The `done` event can be listened too as well.
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function done(callback:Function):AsyncTask{
> > + if(!doneCallbacks){
> > + doneCallbacks = [];
> > + }
> > + doneCallbacks.push(callback);
> > + return this;
> > + }
> > + public abstract function run(data:Object=null):void;
> > +
> > + /**
> > + * cancel resolves the task as "canceled"
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function cancel():void
> > + {
> > + _status = "canceled";
> > + notifyDone();
> > + }
> > +
> > + private var _data:Object;
> > + /**
> > + * The data of the task
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function get data():Object
> > + {
> > + return _data;
> > + }
> > +
> > + public function set data(value:Object):void
> > + {
> > + _data = value;
> > + }
> > +
> > + }
> > +}
> > \ No newline at end of file
> > diff --git
> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/CompoundAsyncTask.as
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/CompoundAsyncTask.as
> > new file mode 100644
> > index 0000000..3dee5ef
> > --- /dev/null
> > +++
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/CompoundAsyncTask.as
> > @@ -0,0 +1,135 @@
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +//
> > +// Licensed to the Apache Software Foundation (ASF) under one or more
> > +// contributor license agreements. See the NOTICE file distributed
> with
> > +// this work for additional information regarding copyright ownership.
> > +// The ASF licenses this file to You under the Apache License, Version
> 2.0
> > +// (the "License"); you may not use this file except in compliance with
> > +// the License. You may obtain a copy of the License at
> > +//
> > +// http://www.apache.org/licenses/LICENSE-2.0
> > +//
> > +// Unless required by applicable law or agreed to in writing, software
> > +// distributed under the License is distributed on an "AS IS" BASIS,
> > +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> > +// See the License for the specific language governing permissions and
> > +// limitations under the License.
> > +//
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +package org.apache.royale.utils.async
> > +{
> > + import org.apache.royale.events.Event;
> > +
> > + /**
> > + * The CompoundAsyncTask class allows running a number of AsyncTasks
> in parallel and resolves when they are done.
> > + */
> > + public class CompoundAsyncTask extends AsyncTask
> > + {
> > + public function CompoundAsyncTask(tasks:Array=null)
> > + {
> > + super();
> > + if(!tasks){
> > + tasks = [];
> > + }
> > + this.tasks = tasks;
> > + completedTasks = [];
> > + failedTasks = [];
> > + }
> > + protected var tasks:Array;
> > +
> > + private var _failEarly:Boolean;
> > + /**
> > + * If <code>failEarly</code> is true, the task will fail as soon as
> the first subtask fails.
> > + */
> > + public function get failEarly():Boolean
> > + {
> > + return _failEarly;
> > + }
> > +
> > + public function set failEarly(value:Boolean):void
> > + {
> > + _failEarly = value;
> > + }
> > +
> > + public function addTask(task:AsyncTask):void{
> > + tasks.push(task);
> > + }
> > +
> > + protected var pendingTasks:Array;
> > +
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > + public var completedTasks:Array;
> > + /**
> > + * @royalesuppresspublicvarwarning
> > + */
> > + public var failedTasks:Array;
> > +
> > + override public function run(data:Object=null):void
> > + {
> > + if(_status == "pending"){// don't allow running twice
> > + return;
> > + }
> > + _status = "pending";
> > + pendingTasks = [];
> > + for(var i:int=0;i<tasks.length;i++){
> > + var task:AsyncTask = tasks[i];
> > + task.done(handleDone);
> > + pendingTasks.push(task);
> > + task.run();
> > + }
> > + }
> > + private function handleDone(task:AsyncTask):void
> > + {
> > + if(_status != "pending")
> > + {
> > + return;
> > + }
> > + var idx:int = pendingTasks.indexOf(task);
> > + pendingTasks.splice(idx,1);
> > + switch(task.status){
> > + case "complete":
> > + completedTasks.push(task);
> > + break;
> > + case "failed":
> > + failedTasks.push(task);
> > + if(failEarly)
> > + {
> > + while(pendingTasks.length)
> > + {
> > + var pending:AsyncTask = pendingTasks.pop();
> > + pending.cancel();
> > + }
> > + fail();
> > + return;
> > + }
> > + break;
> > + default:// not sure why this would happen
> > + throw new Error("Unknown task status");
> > + }
> > + if(pendingTasks.length == 0)
> > + {
> > + setFinalStatus();
> > + }
> > + }
> > + protected function setFinalStatus():void
> > + {
> > + if(failedTasks.length == 0)
> > + {
> > + complete();
> > + }
> > + else if(completedTasks.length == 0)
> > + {
> > + fail();
> > + }
> > + else
> > + {// Some passed and some failed -- Does this make sense?
> > + _status = "mixed";
> > + dispatchEvent(new Event("failed"));
> > + dispatchEvent(new Event("complete"));
> > + notifyDone();
> > + }
> > + }
> > + }
> > +}
> > \ No newline at end of file
> > diff --git
> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/SequentialAsyncTask.as
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/SequentialAsyncTask.as
> > new file mode 100644
> > index 0000000..77f2f18
> > --- /dev/null
> > +++
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/async/SequentialAsyncTask.as
> > @@ -0,0 +1,77 @@
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +//
> > +// Licensed to the Apache Software Foundation (ASF) under one or more
> > +// contributor license agreements. See the NOTICE file distributed
> with
> > +// this work for additional information regarding copyright ownership.
> > +// The ASF licenses this file to You under the Apache License, Version
> 2.0
> > +// (the "License"); you may not use this file except in compliance with
> > +// the License. You may obtain a copy of the License at
> > +//
> > +// http://www.apache.org/licenses/LICENSE-2.0
> > +//
> > +// Unless required by applicable law or agreed to in writing, software
> > +// distributed under the License is distributed on an "AS IS" BASIS,
> > +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> > +// See the License for the specific language governing permissions and
> > +// limitations under the License.
> > +//
> >
> +////////////////////////////////////////////////////////////////////////////////
> > +package org.apache.royale.utils.async
> > +{
> > + /**
> > + * The SequentialAsyncTask runs a list of tasks in sequential order.
> > + * Each sunsequent task is only run once the previous task is done.
> > + * The previous task is used as the argument for the next task's run
> method.
> > + * This enables the chaining of results.
> > + */
> > + public class SequentialAsyncTask extends CompoundAsyncTask
> > + {
> > + /**
> > + * @langversion 3.0
> > + * @playerversion Flash 10.2
> > + * @playerversion AIR 2.6
> > + * @productversion Royale 0.9.6
> > + */
> > + public function SequentialAsyncTask(tasks:Array=null)
> > + {
> > + super(tasks);
> > + }
> > + override public function run(data:Object=null):void
> > + {
> > + _status = "pending";
> > + pendingTasks = tasks.slice();
> > + var task:AsyncTask = pendingTasks.shift();
> > + task.done(handleDone);
> > + task.run();
> > + }
> > + private function handleDone(task:AsyncTask):void
> > + {
> > + if(_status != "pending"){
> > + return;
> > + }
> > + switch(task.status){
> > + case "complete":
> > + completedTasks.push(task);
> > + break;
> > + case "failed":
> > + failedTasks.push(task);
> > + if(failEarly){
> > + pendingTasks = [];
> > + fail();
> > + return;
> > + }
> > + break;
> > + default:// not sure why this would happen
> > + throw new Error("Unknown task status");
> > +
> > + }
> > + if(pendingTasks.length){
> > + var nextTask:AsyncTask = pendingTasks.shift();
> > + nextTask.done(handleDone);
> > + nextTask.run(task);
> > + } else {
> > + setFinalStatus();
> > + }
> > + }
> > + }
> > +}
> > \ No newline at end of file
> >
>
>
--
Carlos Rovira
http://about.me/carlosrovira