PureMVC Architects Lounge

PureMVC Manifold => Demos and Utils => Topic started by: puremvc on November 12, 2008, 06:37:02



Title: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on November 12, 2008, 06:37:02
The AsyncCommand utility offers a solution to the problem of executing a series of commands each of which may need to complete one or more asynchronous operations before the next command is executed.

The utility has historically been located here: http://trac.puremvc.org/Utility_AS3_AsyncCommand
The project has been moved here: https://github.com/PureMVC/puremvc-as3-util-asynccommand/wiki

Standard and MultiCore versions are included.

The author is Duncan Hall.


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: mister_t on November 25, 2008, 12:14:37
Is there also an action script (as3) version of this utility? As far as I know flash can't import .swc files with only class definitions in it.


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on November 25, 2008, 12:41:26
Yes, for flash, simply put the classes in your classpath. Checkout the release notes page for the AS3 port for info about the varios ways you can do this.

-=Cliff>


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on December 10, 2008, 08:16:01
feature request:

mmm I really want a pre nextCommand hook:


public final function execute( notification:INotification ) : void{
    note = notification;
    onCommandEnter()
    nextCommand();
}

protected onCommandEnter():void{}

any chance?? :)


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on December 10, 2008, 08:41:36
better make it onCommandEnter( notification )


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on December 10, 2008, 08:43:04
so I can do this:

override protected function onCommandEnter( notification:INotification ):void{
   var note:INext;
   note = notification as INext
   addSubCommand(note.getNext())
}


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on December 10, 2008, 10:52:43
Hi Fleecie,

I see what you're after, but it seems like an edge case. I gather you want an AsyncMacroCommand to open a Notification and use it to dynamically discover the next command.

In the example you give, presumably the next command hasn't been defined yet and is not actually being added to the end of a long list of sub commands. Otherwise there'd be no point in doing this evaluation for each command in the list. It would fail if each notification didn't return a new command to be added, so execution of each command in the list would end up adding another command to the list? Seems like it could get out of hand pretty quickly.

I think it's possible that you might find what you want by using the StateMachine utility in conjunction with the AsyncCommand utility. With the StateMachine, you get notification that you're exiting one state and another that you're entering the next, and you can cancel a transition from the exiting notification.

-=Cliff>


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on December 10, 2008, 01:13:10
I thought you might say something like that :)

hey hold on your right! looking at it again, i see that I've made a huge error... I actually want to extend the nextCommand()   thus:

 override protected function nextCommand():void{
var note:INext;
         note = notification as INext
         addSubCommand(note.getNext())







Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on December 10, 2008, 02:33:54
That looks right.

-=Cliff>


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on December 10, 2008, 02:54:44
sorry, had a server error this is the whole post


actually want to extend the nextCommand()   thus:

override protected function nextCommand():void{
    var note:INext = notification as INext;
    var nextClass:Class = note.getNext()
    if (nextClass != null)   addSubCommand(nextClass)
    super.nextCommand();

}

In this way the subcommands would be created dynamically instead of through the initializeCommand() method.  I completely see that this is a very specialised and unique case that doesn't really warrant a change.  It would just be a nicer to extend the AsychCommand Utility from a swc than create "parallel" code

cheers






Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: willw on March 11, 2009, 03:49:36
I think there is a bug in AsyncCommand.as.

The example code only considers AsyncCommand instances being invoked from an AsyncMacroCommand.

If an AsyncCommand is not run from an AsyncMacroCommand, then setOnComplete() is not called for that instance, and onComplete remains null. So when the code in AsyncCommand calls commandComplete() to indicate it has finished, the code barfs.

The cure, I suggest, is to test for an uninitialised onComplete member in commandComplete(), like this:
:
/**
 * Notify the parent <code>AsyncMacroCommand</code> that this command is complete.
 * <P>
 * Call this method from your subclass to signify that your asynchronous command
 * has finished.
 */
protected function commandComplete () : void
{
if (onComplete != null)
onComplete();
}

After this, AsyncCommands can be used standalone and in macros.

Will


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Tekool on March 11, 2009, 04:49:55
Willw, it's up to you to call the onComplete handler from a standalone AsyncCommand instance.

Look at the comment :

* Call this method from your subclass to signify that your asynchronous command
* has finished.

So it's not a bug. The class do not know the logic that drive to the end of the execution of the asynchronous process, the instance have to call *onComplete* itself to notify of the end of the asynccommand execution.


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: willw on March 11, 2009, 05:08:30
So it's not a bug. The class do not know the logic that drive to the end of the execution of the asynchronous process, the instance have to call *onComplete* itself to notify of the end of the asynccommand execution.

1. You seem to be confusing commandComplete(), a protected method, and onComplete, a private instance variable containing a pointer to a function. It is commandComplete() that one is supposed to call - onComplete is not in scope in an inherited class.

2. Yes, it is a bug. If the inherited code (correctly) calls commandComplete() from a standalone AsyncCommand (ie not run as a macro) to notify end of execution, then onComplete is null, and the program dies.

Will


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Tekool on March 11, 2009, 05:50:28
@willw You're right, you must understand *commandComplete* not *onComplete*.

To be honnest, I can't see the context where you need an AsynCommand to call *commandComplete* without to have a wrapper that declare the *onComplete* callback like in the AsynMacroCommand. But you're right, your patch will prevent any use of the AsyncCommand as a SimpleCommand.


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: willw on March 11, 2009, 06:00:45
To be honnest, I can't see the context where you need an AsynCommand to call *commandComplete* without to have a wrapper that declare the *onComplete* callback like in the AsynMacroCommand. But you're right, your patch will prevent any use of the AsyncCommand as a SimpleCommand.

The point is that a AsyncCommand shouldn't care whether it is being used standalone or as part of a macro. It should work either way, without needing to change its behaviour. For example, you may design an AsyncCommand to be used by itself, and subsequently add it to a macro.

Will


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Tekool on March 11, 2009, 06:06:22
I do not know what Cliff will say, but now your request seems fair to me. Sorry not to have understood immediately.  :-[


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Ondina on March 11, 2009, 06:46:50
In my app I have lots of comboboxes as a part of a form, that need to be populated on the creationComplete of the view.

I have only one proxy  for retrieving the combos' data from the server.

Instead of having an AsyncCommand for each combo I (mis)used an AsyncCommand that calls itself 
( in the callBack function of the asynccommand where I have the commandComplete())
 until all combos have data.

I used an AsyncMacroCommand to call the AsyncCommand because when I called the AsyncCommand alone the debugger said that onComplete was null. I didn't know the meaning of that error.
So I thought I misused the AsyncCommand.

After seeing this post I made the changes suggested by Will and now the AsyncCommand works fine.


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on March 13, 2009, 07:06:37
My impression of AsycCommand is that it doesn't make any since to use it outside the context of an AsyncMacroCommand. The macro is looping until the children report completion. The only difference between a SimpleCommand and an AsyncCommand is that the latter is capable of storing and invoking the callback when done. What reason would one Have for using it outside that context?

-=Cliff>


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Ondina on March 13, 2009, 08:52:51
Hi Cliff

Yeah, you are for sure right, I'm using the AsyncCommand outside of  its scope, but how would you solve this issue:

I have a ViewStack with let's say 8 Views.
Each View contains a form.
Many of those forms contain several ComboBoxes with their dataProvider coming from database tables.
When the View is created the ComboBoxes should get their data.
So one ComboBox after another receives the dataProvider from server.

If for some reason the remote call failed, I have to try to reload the data.
For that to happen I have to let the Mediator know that the data for a certain ComboBox is missing and the View should enable a Button that would let the user call the server again for this particular ComboBox.

Instead of having an AsyncMacroCommand with 3 AsyncCommands ( AsyncCombo1, AsyncCombo2, AsyncCombo3 )  for the first View and then another AsyncMacroCommand with 5 AsyncCommands (  AsyncCombo4, AsyncCombo5 and so on ) for another View, I made ONE AsyncCommand for all the Combos in all my Views.

The Mediator of each View calls this ComboAsyncCommand passing it an array of the combos that need data in the body of the Notification.

The AsyncCommand  retrieves the only one proxy ( ComboProxy ).
The ComboProxy  reads the needed info ( for example the name of the database table ) from a  ComboVO ( common to all the combos ).

When data has arrived the ComboPoxy sends a notification for the Mediators ( the combo gets its data ) and calls the  callBack function in the ComboAsyncCommand , that is then ready for the next Proxy call.

If for some reason I have to change or rearrange  the ComboBoxes in my views, I only need to tell the View's Mediator the new ID of the Combobox, which is the same name as the database table.

I (mis)used the AsyncCommand because it is already there with the ability of getting and sending Notifications and its onComplete method. 
In the callBack method of the Command I can send a Notification for the Mediator in case of an rpc FaultEvent, but I can continue with the  calls for the rest of the ComboBoxes.

I can as well call the ComboAsyncCommand in an AsyncMacroCommand together with another AsynCommand that would call a Proxy for a DataGrid if the View needed both.

Before making the changes suggested by Will, I had an AsyncMacroCommand calling a single AsyncCommand over and over again until all Combos had data.

Oh... I hope my explanation isn't too convoluted and you'll understand what I meant.
Maybe I really don't need an AsynCommand, but I didn't know how else to do it.
I would really appreciate it, if you showed me a better solution for this kind of problem.

Thanks, Ondina


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: willw on March 13, 2009, 09:30:28
As I said to Tek, surely the point of having AsyncCommands is that they can be compounded into macros or not, as the need arises.

The current code prevents this. A correctly-written AsyncCommand cannot be used by itself. There is no indication in the docs to suggest that this is intentional.

The proposed correction breaks no code AFAICS. It seems uncontroversial to me.

Will




Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on March 13, 2009, 08:43:08
Ok, maybe I'm missing the point. How does a standalone AsyncCommand differ from a SimpleCommand in such a way that would cause you to use it as anything other than a subcommand of an AsyncMacroCommand?

@Ondina, I tried to follow your explaination, but you said that you passed the array oc combos to your ComboAsyncCommand, it populates them and then calls its commandComplete method? That's where I lose track. Will's suggestion jus plugs the hole of trying to invoke the callback if it isn't there. Which it isn't. So it doesn't do anything. I.e. Isn't any different from a SimpleCommand doing its work then ending.

Its late so I may have missed something crucial, but otherwise, substitute a SimpleCommand and see if it doesn't work the same.

-=Cliff>


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Ondina on March 14, 2009, 04:26:25
Hey Cliff

OK. Forget about that array.

Let's start by the definition:

"The AsyncCommand utility offers a solution to the problem of executing a series of commands each of which may need to complete one or more asynchronous operations before the next command is executed."

I might have misunderstood the idea of the AsyncCommand, but isn't it that commandComplete();   that lets the AsyncMacroCommand know when to call the next command?

Of course I can use a SimpleCommand to loop a service call. It works just fine if I used it alone.

But if I need the same (Simple) command in an AsyncMacroCommand  the “next” command is called simultaneously and not after the SimpleCommand has completed.

1. So let's say in an AsyncMacroCommand I add the subcommands:

SimpleCommandOne (without any looping , without any arrays,  just a simple proxy call)
SomeOtherAsyncCommand
SimpleCommandTwo
AnotherAsyncCommand

Here I can't control in which order they would execute.

2. But if I had

SimpleAsyncCommandOne (without any looping , without any arrays,  just a simple proxy call)
SomeOtherAsyncCommand
SimpleAsyncCommandTwo
AnotherAsyncCommand

everything works as it should.

The problem is that I  need the SimpleAsyncCommandOne somewhere else in my code to be called outside of an AsyncMacroCommand and I can't do that without that hack:

protected function commandComplete () : void
{
   if (onComplete != null)
   onComplete();
}

--
The more real scenario :

View1's mediator
ComboAsyncCommand called standalone . ( for 3 ComboBoxes)

View2's mediator:
An AsyncMacroCommand calls
ComboAsyncCommand ( for 1 ComboBox)
DataGridAsyncCommand (for 1 DataGrid)
ListAsyncCommand ( 1List)
AnotherAsyncCommand ( for some other reason)

View3's mediator:
DataGridAsyncCommand standalone (for 2 DataGrids)

View4's mediator:
An AsyncMacroCommand calls
ListAsyncCommand (2 Lists)
ComboAsyncCommand ( for 4 ComboBoxes)
--

I still would like to know how to do it better.

So I don't want to prove anything, I'm just trying to find my way through the puremvc labyrinth.
As I said I might be the one confusing things and if it is so, please  excuse my newbiness  and my not so good explanations :)

Ondina


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: willw on March 14, 2009, 09:11:03
How does a standalone AsyncCommand differ from a SimpleCommand in such a way that would cause you to use it as anything other than a subcommand of an AsyncMacroCommand?

Look at it the other way round. If you have an AsyncCommand that, you realise, can be useful standalone, why should you have to duplicate its code as a SimpleCommand to use it?

or

If you design a command that is intrinsically asynchronous (eg it makes a round trip call to the server), why wouldn't you design it as an AsyncCommand rather than a SimpleCommand, and thereby reserve the opportunity to compound it into an AsyncMacroCommand if the need arises?

We seem to be making heavy weather of this. The suggested change is very cheap, and is invisible to those who don't care... but allows an expected use to work for those who do. I feel I have already written more than enough to justify it. If you don't want it, well, fair enough.

Will


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on March 15, 2009, 08:31:15
The simplicity of change isn't the point. The point is the AsycCommand is absolutely useless in any context other than as a subcommand of an AsyncMacroCommand. Its call for completion is meaningless.

And the danger is that someone thinks that the thread of execution has stopped during the asych activity, which is not the case unless it is a sub of an AsyncMacroCommand. In any other setting, the thread of execution keeps right on truckin'.
 
Btw, I am not the author of this utility, that is Duncan Hall. You may wish to take up the question with him.

-=Cliff>


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: willw on March 16, 2009, 12:37:23
The point is the AsycCommand is absolutely useless in any context other than as a subcommand of an AsyncMacroCommand. Its call for completion is meaningless.
You keep saying this. It just isn't the case.

An AsyncCommand 'has meaning' for example if you wrap it around a remote call. When the remote call returns, it can take appropriate action (handling failure, notifying  other participants), and finally call commandComplete().

Why would I only run the above in the context of an AsyncMacroCommand?

And the danger is that someone thinks that the thread of execution has stopped during the asych activity, which is not the case unless it is a sub of an AsyncMacroCommand. In any other setting, the thread of execution keeps right on truckin'.
Not true.

If you write asynchronous code, the thread continues executing irrespective of AsyncMacroCommand's involvment. All AsyncMacroCommand does is get control back at some point in the future and pass it to the next command.
 
Btw, I am not the author of this utility, that is Duncan Hall. You may wish to take up the question with him.

Ok, if that's the right thing to do. How do I contact him?

Will


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on March 16, 2009, 03:07:51
So, when you finally call commandComplete on an AsyncCommand, what exactly is it that you wish to happen? If it is not a subcommand of an AsyncMacroCommand, its like the sound of one hand clapping. It signifies nothing. No one is listening.

As for the thread of execution, if an AsyncMacroCommand is running, the thread is running, but in a loop in the AsyncMacro which is waiting for the subcommand to report completion. If you don't have the macro running then your thread moves on. So someone might think well I can just use the AsyncCommand and further processing will be suspended until I call commandComplete, which actually does NOTHING at all without the AsyncMacroCommand.

The project page for each utility has a link to the author's page, which has their email address, so if you'd like to talk to Duncan about making this change, just send him an email.

BTW, I agree with the change, I just don't agree that the AsyncCommand has any use whatsoever outside the context of its attending AsyncMacroCommand and want anyone reading this thread to understand why. Personally, I rarely do service interaction in commands (Cairngorm style). Since most service interactions end up pulling data into the client that will be used for display and or update back to the server, a long lived entity is more appropriate, which is why the best practices doc suggests use of proxy or proxy/delegate as the preferred method of handling services.

Recently I have found a few service use cases that makes sense to handle in a command; checking for internet connectivity before proceeding with startup in an AIR app that requires net connectivity to do its job, then checking that the user has a valid licens, then checking that the user has an S3 account. In this sequence, I looes at AsyncCommand and several other approaches, and in the end I found that the combination of the StateMachine with SimpleCommands was the easiest answer. The states of 'checking internet', 'checking license', 'checking S3' kick off SimpleCommands with their state-specific 'changed' notes, and sinc the machine is sitting in a given state and is only kicked out of it and into the next state when a given StateMachine.ACTION note is sent, its easy to have the command make the call get the result and send a result or failure notice. The StateMachine then moves to the next state (or a tangential state such as 'offline' or entering license' or 'entering S3 credentials'. Of course, after entering license info, I move to a 'saving license' state then back to the 'checking license' state in a loop until license check passes, then on to 'checking s3' where a similar loop happens if credendials haven't been entered and saved.

Handling that sort of multistep process where each step could fail and needs to be addressed before the train moves to the next stop a big ugly bear that just crawled from a foul smelling swamp if you approach it with a linear 'chained command' approach. If you're going that route then the StartupManager utility is far more appropriate because the failure recovery options have been addressed in a very elegant way.

-=Cliff>


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Ondina on March 17, 2009, 02:30:46
Hi Cliff

If it is not a subcommand of an AsyncMacroCommand, its like the sound of one hand clapping. It signifies nothing. No one is listening.

Yea pure Zen :)

the AsyncCommand and further processing will be suspended until I call commandComplete, which actually does NOTHING at all without the AsyncMacroCommand.

That's true. The commandComplete  does nothing when it is used in a standalone AsyncCommand.
An AsynCommand called outside an AsyncMacroCommand behaves like a SimpleCommand and that's the way I used it, as a SimpleCommand in one place and as an AsyncCommand in another context.

So if I wanted to go by the rules I should have written 2 Commands , one SimpleCommand and one AsyncCommand having the same code inside, of course with  the SimpleCommand not having the commandComplete .  It wouldn't be a big deal to duplicate that code for a (one) situation like this. But my application is huge, I have many similar situations and if I wouldn't reuse the code  I would have lots of Commands that would behave against the DRY principle.


Personally, I rarely do service interaction in commands (Cairngorm style). Since most service interactions end up pulling data into the client that will be used for display and or update back to the server, a long lived entity is more appropriate, which is why the best practices doc suggests use of proxy or proxy/delegate as the preferred method of handling services.

Well now I'm really confused. I'm not sure which part of your post is addressed to me and which to Will or if it is just a general observation.


I don't make the service call in the commands. I retrieve the proxies there and call their methods.
Is this a bad way to do it?

In my code the Proxy is handling the services.
I also have a “RemoteDelegate” called by different Proxies with different endpoints and different requests.
The route is like this:

View->Mediator->Command->Proxy->Delegate
Delegate->Proxy->Mediator->View

The View needs data, the Mediator calls the Command, the Command retrieves the Proxy, the Proxy gets the service result from a Delegate and sends a Notification to the Mediator, which takes the note.getBody() object and populates the View's ComboBox with that object.
Of course if I showed you the code it would be easier to understand what I'm talking about, but    since you are on your BlackBerry you wouldn't see it anyway.


Handling that sort of multistep process where each step could fail and needs to be addressed before the train moves to the next stop a big ugly bear that just crawled from a foul smelling swamp if you approach it with a linear 'chained command' approach.

So now where should I make the loop for the service call, if not in the command?

A.Should I do it in the Mediator?
  1.Calling a SimpleCommand repeatedly
  2.calling a Proxy repeatedly (meaning same code in each Mediator that needs data from server)
B. Should I call the Proxy in a Command  repeatedly?
C.Should I loop the service call in the Proxy itself?

You mention the  StartupManager.
Are you suggesting that I should use the  StartupManager for each View that has ComboBoxes that need to be populated with data from the server?
In the  StartupManager example there are 3 different Proxies for 3 different sets of data.
I have one Proxy for similar data ( ComboBoxes dataProvider).
I don't quite understand  right now how I can use it.
Hopefully I will be able to find a solution without bothering you again:)
I'm sorry for the inconveniences I caused in here.

Ondina


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: willw on March 17, 2009, 03:21:53
So, when you finally call commandComplete on an AsyncCommand, what exactly is it that you wish to happen? If it is not a subcommand of an AsyncMacroCommand, its like the sound of one hand clapping. It signifies nothing. No one is listening.
I don't understand why we are struggling with this so much, because it really, really isn't very hard. I must be putting my point over really badly.

Let's break it into steps, and see if we can't identify the point where we diverge

1. AsyncCommand is a convenient wrapper for any process that completes asynchronously. Ok? You may not approve of its use, but that's how I use it, in fact using a design of your suggestion - which works very well for me. See first para here:
When you invoke the Proxy method to make the remote call, pass a Function typed reference[...]

2. When the remote call returns control to the proxy, it uses a callback to raise the second part of the AsyncCommand, just as suggested in your design.

3. The second part of AsyncCommand completes its business. Typically it emits a notification.

4. Finally, because this AsyncCommand doesn't know whether or not it is part of a macro, it must call commandComplete(). I repeat: it does not know whether it is a subcommand or standalone. So the whole business of 'one hand clapping' does not arise. It doesn't care whether it has a parent or not; it just knows that it must notify a parent if it happens to exist. So commandComplete() mustn't barf if it happens not to have a parent. Because it has to call commandComplete() anyway. Because it doesn't know. Pant, pant, pant ;-)

As for the thread of execution, if an AsyncMacroCommand is running, the thread is running, but in a loop in the AsyncMacro which is waiting for the subcommand to report completion. If you don't have the macro running then your thread moves on. So someone might think well I can just use the AsyncCommand and further processing will be suspended until I call commandComplete, which actually does NOTHING at all without the AsyncMacroCommand.
Sorry, but this is quite wrong. But we needn't have this as an abstract argument.

Here is the code from http://puremvc.org/pages/utils/AS3/Utility_AS3_AsyncCommand/srcview/ (http://puremvc.org/pages/utils/AS3/Utility_AS3_AsyncCommand/srcview/); this is the key function from AsyncMacroCommand.as:
:
        private function nextCommand () : void
        {
            if (subCommands.length > 0)
            {
                var commandClassRef:Class    =    subCommands.shift();
                var commandInstance:Object    =    new commandClassRef();
                var isAsync:Boolean            =    commandInstance is IAsyncCommand;
               
                if (isAsync) IAsyncCommand( commandInstance ).setOnComplete( nextCommand );
                ICommand( commandInstance ).execute( note );
                if (!isAsync) nextCommand();
            }
            else
            {
                if(onComplete != null) onComplete();
               
                note         =    null;
                onComplete    =    null;
            }
        }                     
The key thing to note is that, if executing an asynchronous command, it drops out of the function. It is not in a loop! It couldn't be, otherwise nothing else could happen within the main Flash thread.
(Whereas with a simple command, it does indeed loop around, calling itself recursively. This is what this line is about:
:
                if (!isAsync) nextCommand();
but you notice it specifically excludes asynchronous commands.)

So anything can happen when an AsyncCommand or an AsyncMacroCommand is executing, and there is no difference between the two in terms of thread loops. They are both waiting for a callback.

Now (I hope) I have cleared that up for you, perhaps we are nearer to seeing eye to eye regarding how AsyncCommand works.

The other thing that is amusing to notice is that this code already contains exactly the test that I propose for AsyncCommand
:
                if(onComplete != null) onComplete();
This test is there for exactly the same reason that I suggest it: AsyncMacroCommand in turn may (or may not) be aggregated into further AsyncMacroCommands - but the code in each level doesn't 'know' whether this has happened or not.

The project page for each utility has a link to the author's page, which has their email address, so if you'd like to talk to Duncan about making this change, just send him an email.
Thanks - will investigate.

Since most service interactions end up pulling data into the client that will be used for display and or update back to the server, a long lived entity is more appropriate, which is why the best practices doc suggests use of proxy or proxy/delegate as the preferred method of handling services.
I use a proxy to handle services - as per the recommendation. I also call proxy functions from the commands. By making the command asynchronous, I found I could contain the whole business of handling the callback within the context of the command.

I tried modelling the system with state changes - ie the arrival of the data in the proxy generated a notification, which caused a state change. This worked, but I like the localisation of the service call that is provided by the AsyncCommand. By handling remote calls in a single command, nothing else has to 'handle' them.

By the way, I still use the proxies to do all the data handling. In effect, what I have done is replace the notification emitted by the proxy in classic pureMVC design by a callback to the owning AsyncCommand. This means I don't have to declare any notification string constants in proxies, and so don't have to reference the proxies in any mediators (because the notifications are emitted by the commands). So I break completely the dependency of the mediator on the proxy - it's another gain for separation of concern.

However, as you know, I am absolutely an enthusiast for state machines, and definitely advocate their use in these types of applications. There are no swamp-smelling bears in my app! :-)

Will


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Gallo_Teo on March 17, 2009, 09:48:15
hi everybody, with the scope tu always use async command instead of simpleCOmmand i modified this simply line in asyncCommand class

protected function commandComplete () : void
      {
         if ( onComplete != null )
            onComplete();
      }

hope helpful

Teo


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on March 17, 2009, 03:37:56
@willw, Aha! Thanks for sticking through this with me. I had an imperfect understanding of the AsyncMacroCommand. When I originally looked at it I misinterpreted the "if (!isAsync) nextCommand();" as a loop. I see now it clearly lets the thread keep on going. Which makes me scratch my head all the more on the use of the entire utility. I get that it causes AsyncMacroCommand (herinafter refered to as the macdaddy) not to execute the next subcommand until the current one completes, but if it's not blocking, (i.e. holding the thread in a loop until completion of the subcommand) then I can't imagine ever using it, period. Why?

Lets say I've got 3 AsyncCommands that I want executed before moving to the next state. They all fetch data that is needed by that destination state and they need to happen in order because one uses the results of the previous to make its call. But while one of them is off waiting, the user does something that causes a transition to another state wherein I don't want that data I was in the process of fetching. So the StateMachine moves to the new state, but the Macdaddy is still in memory as well as the waiting subcommand, which now gets its data, calls commandComplete, and then its Macdaddy now happily moves on to execute the next (now unwanted) subcommand which goes and fetches a huge gob of useless data.

Based on this understanding, for my part, I'll never use or advocate IAsyncCommands if the AsyncMacro is non-blocking. You can do the same thing in a SimpleCommand as an AsyncCommand, and the StateMachine can guarantee you aren't going to run into the problem described above. Use it if you want, but just be aware of that scenario and the limitation of the utility.

Myself, I'd prefer to identify each of those processes as discrete states. That gives you much more control over the result/fault branching that needs to be handled for each call. And the entire process is definable in XML in the FSM definition. Once you begin defining your app as a StateMachine all this tedious coordination of chained commands (and the lack of blocking and how to tell the remaining ones that they don't need to run because the whole process they were a part of has been canceled) goes away.

-=Cliff>


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on March 18, 2009, 02:32:43
Yep, thats what I found when I tried to implement a Asynchronous StateMachine transition using the Mcdaddy: http://revisual.co.uk/?cat=61



Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: willw on March 18, 2009, 03:01:09
@Cliff: Excellent news that we have resolved this - I was afraid that one or both of us was going mad!

On the general discussion: certainly AsyncCommand and macdaddy (much improved terminology) have the drawbacks that you say. I have not used a macdaddy yet, and expect its application to be quite limited, for the sorts of reasons you say. But I can imagine wanting to make a McSimpleCommand sandwich: say a Simple followed by an Async followed by another Simple.

AsyncCommand I have found to be good in two use cases: calling services, and also for handling modal dialogs.

Modal dialogs don't block the thread, but they do something rather like it, by restricting the user typically to Ok and Cancel buttons. So you get something very like the blocking behaviour. If you have the initial part of an AsyncCommand launch the modal dialog, and have the completion part process the result and take appropriate action, then you have all the logic for your dialog handling neatly localised in one place.

Calling services with AsyncCommand I have discussed at length, I know. But you may have missed my point that using AsyncCommands in this way enables you to remove the notification constants declared in proxies. Why would one want to do this? Because it means that mediators that depend on data from the proxies wrapped up in a VO don't need to import the proxy. Sure, the AsyncCommand does, but it would do so anyway. It means one doesn't have to hunt through proxies for notification constants too.

The drawbacks you mention to AsyncCommands are mostly true (although I have no 'tedious coordination of chained commands', honest), but if you plan for them you discover they may not matter. If the data arrives too late because the punter has changed his mind, then so what? If your app continues to be responsive, even at the hands of an impatient clicky user and a slow data feed, then that is a win.

The main drawback with the approach based on states is: when I tried it I ended up with a LOT of states, in order to cope with all the 'waiting for an answer' situations I needed to handle. I found this was clouding my view of how the whole machine worked. I want to keep the state machine only for very high level features; I found I could push a lot of detail into AsyncCommands and hide it there.

This is of course all extremely subjective and Your Mileage May Vary.

I do feel pretty bullish about the way I have got my app organised. Of course the bedrock is the base PureMVC architecture, which has proved great. I mention this because you may think I lose sight of this point in the heat of discussion - I don't.

Will


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on March 18, 2009, 05:00:37
@willw, True that. Discussions between coders that really love their work can get pretty hot sometimes. That's passion for ya. :)

I can see that if you want a less granular state machine then a combo of the 2 utils is probably the way to go.

@neil, you reported this lack of blocking before as well, I just didn't get the time to put my mitts on the utility until recently.

I have a pretty good sized FSM definition, but I'm happy to have the whole system expressed there. If you think about it, those application states exist, even if you aren't using the state machine. Its just that by using it, you make them concrete. You can look at the FSM definition and see the whole story.

I want to build a middleware tool for creating, visualising and testing the fsm definition. That would make it easier to take the fine-grained approach.

-=Cliff>


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on March 19, 2009, 02:33:45
@ cliff

I want to build a middleware tool for creating, visualising and testing the fsm definition.

If you wanna farm some code of that out, Id be happy to help...



Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on March 20, 2009, 05:43:40
Neil,

I'd be extremely happy to have the help, because honestly, it'll be awhile before I can get to it.  I was thinking of using Flare for visualization: http://flare.prefuse.org/apps/index

Have a look and see if it looks easy enough to work with.

I was thinking it would generate an AS3 file with the static constants in it, as well as an InjectFSMCommand that looks like the StopWatch one where the constants are bound into the XML. Otherwise if you use literals, you still have to define constants that match those literals in order to register the commands or for the mediators to express interest.

-=Cliff>


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on March 28, 2009, 08:29:33
have had a quick look at fuse.
will have a more in depth look when I have some time to myself.. which should be in a few weeks ;)


Title: Subcommands with different Inote
Post by: crypt on May 10, 2009, 03:12:02
Hi!

I have created a PageChangeCommand (AsyncMacroCommand) with 2subcommand:

addSubCommand( PageHideCommand );
addSubCommand( PageShowCommand );

I would like to hide the current page, and if it is finished, show the next page.

PageShowCommand on execute command:
var page:Page = facade.retrieveMediator(note.getBody() as String).getViewComponent() as Page;
page.showEffect();

PageHideCommand on execute command:
var page:Page = facade.retrieveMediator(note.getBody() as String).getViewComponent() as Page;
page.hideEffect();

But the notification is the same in the 2subcommand...

I use this 2 command (pagehide, pageshow), as standalon command elsewhere in application too.

how can i do this?
thanks!


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: crypt on May 10, 2009, 11:01:18
so the main question is, can I pass different notifications to subcommands?


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on May 11, 2009, 12:48:40
try sending an array of your proxynames as the body of the notification, then each command can pop them off...


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: crypt on May 11, 2009, 01:13:12
thanks! good idea! :-)


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: willw on May 11, 2009, 01:20:41
In a similar situation recently, I thought of this approach - sending in an array and modifying it - and I would certainly expect it to work.

But I can't help feeling a mod to addSubCommand() would be clearer, though, and more generally applicable. There seems no reason AFAIK why subcommands should not take parameters. It would make them generally more useful and powerful.

Will


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on May 11, 2009, 01:28:21
Well, for the basic pureMVC, I think the solid, simple way is best... and there is always a fairly simple solution for most problems ( and don't for get that commands can modify just the notification if needed ).

However, as an additional "bolt on" utility that builds on the basic, I think that this is a grand idea... over to you Will... :)

(oooh, and while your there, I've also also like the idea of being able to inject subcommands at run time too... that would be awesome! )


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: willw on May 11, 2009, 03:56:56
don't forget that commands can modify just the notification if needed

The trouble with commands modding the notification is that it means that the command becomes 'aware' of its context. This is also my problem with eating the array of parameters as you go along. It works, but you are spreading knowledge of the parameter mechanism, and the outside environment, into the sub command. The subcommands become more tightly coupled than one wants.

And yes, I would like to come back and have a go at this and a few other things. There are some straightforward mods that I made to to the State machine which I claim improves its decoupling considerably. I would like to share, if Cliff is up for it.

But not today.  Today I am on a code death march! :-o

Will




Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on May 18, 2009, 03:07:26
The trouble with commands modding the notification is that it means that the command becomes 'aware' of its context.

agreed, and you can also add that any code must have some awareness of its environment, but no more than necessary.

The command "knows" the framework, the command is there to do a certain job on a certain object - even if that object is hiding behind an interface, it must know that interface. It must know how to obtain it, whether from the notification body, or retrieving it from the framework.

so what is the difference between passing a proxy name in the body, or an array of proxy names, the command is expecting one or the other or either.

your command could type check the note body, use a string or pop from an array, or an array collection, or a linked list, or whatever. It could even take a leaf from "Chain of Responsibility", and if it can't do its job in the environment it was expecting, it pass the job on to the next command, which may be able to.

what is the difference between passing an array of proxy names in a notification, which is modified by a command and passing a proxy in a notification which is modified by a command? or are you saying that to pass an object in a notification to a macrocommand is to tightly couple its subcommands?  I'm not sure about this.  Also, if any tight-couplings are to appear in your application where better that in your commands, which tend to be (though not exclusively) tightly coupled to the application in which they are implemented.





Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: willw on May 19, 2009, 03:52:36
I am saying that if you require that a command mods a notification in order for the next command to work, you are indeed introducing a coupling between the commands that didn't previously exist. You cannot now introduce 'any' command into the sequence - for example a command that expects a certain VO as its note body (say). It must be a command designed to consume the array of (whatever - proxies in this case).

Whereas, if you have a variation of addSubCommand() that can pass in params (or not, as required) then the subcommands remain quite ignorant of each other's existence, and so can be re-used freely and intermixed with one another in other macro commands or used standalone, without imposing the requirement that they handle the note body in a certain way.

Will


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: Neil Manuell on May 19, 2009, 03:55:58
true :)


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: skasssam on October 26, 2012, 06:25:58
I hope I'm not beating a dead horse but I am really looking for some guidance here.

I have certain situations where I need to call a certain sequence of Proxy calls (same proxy different methods) and they must be completed in a certain order.

I have it currently implemented like:
Mediator A -> Proxy A.1 -> Mediator A-> Proxy A.2 -> Mediator B -> Proxy A.3

I thought there was a better way to do this since following a trail of Notifications doesn't seem right.

Initially it looked like AsyncCommand could help me with something like this but after reading the thread I'm not sure.

I was hoping that the AsyncCommand could help me do something like this:
Mediator A -> AsyncCommand

My AsyncCommand would have AsyncSubCommands that would have calls to the ProxyA.1, A.2....

Is this a good use case for the AsyncCommand to help me get rid of the trail (and back and forth between mediator and proxy) of notifications?

TIA
Shinan


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on October 26, 2012, 08:32:08
Yes, it is a good approach. However if you need to do something with the result of the first call before making the second call, (such as extracting the args for the next call), then you might run into trouble since the command won't hear any notifications coming back from the Proxy, and should not place listeners on the Proxy's service.

Another good approach that takes care of this (and doesn't require AsyncCommand) is the ServiceRequest pattern, which I describe in the O'Reilly book [1].

Essentially, a normal Command can send a formal request (based on Observer, and containing a callback to the command) to a Proxy method. The Proxy hangs onto the request (keeping the Command in memory since it has a reference). When the service returns, the Proxy sends the data back to the caller (the Command), which can then make the next request. You could make all your calls from the same SimpleCommand OR you could have a MacroCommand with three SimpleCommands that all do this. The first subcommand could set the results in the body of the note for the second subcommand to use and so on.

Although I think you'd find the explanation in the book more complete, here are some links to the relevant code:

The ServiceRequest class:
http://examples.oreilly.com/0636920022459/StoryArchitect/src/com/futurescale/sa/controller/command/story/SearchStoryCommand.as

A Command that creates the request:
http://examples.oreilly.com/0636920022459/StoryArchitect/src/com/futurescale/sa/controller/command/story/SearchStoryCommand.as

A Proxy that handles the request:
http://examples.oreilly.com/0636920022459/StoryArchitectModel/src/com/futurescale/sa/model/proxy/StoryReadingProxy.as

Also, this formal request pattern works for any async operation, and the application in the book also makes use of it to allow commands to request a popup and get called back with whatever the user's choices/input were. This makes it a really useful pattern.

Just for fun, here's the popup subsystem. Notice how the AbstractPopupMediator handles the request and the subclasses just have to basically return a different popup component and be interested in a particular notification:
http://examples.oreilly.com/0636920022459/StoryArchitect/src/com/futurescale/sa/view/popup/

Cheers,
-=Cliff>
[1] ActionScript Developer's Guide to PureMVC http://oreil.ly/puremvc


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: skasssam on October 26, 2012, 08:49:19
Thanks Cliff,

I have additional questions about the the implementation in the demo.

This makes sense:
:
public class ExampleAsyncMacroCommand extends AsyncMacroCommand
{
/**
* Execute the SubCommands.
*/
override protected function initializeAsyncMacroCommand () : void
{
addSubCommand( FirstAsyncCommand );
addSubCommand( SecondAsyncCommand );
addSubCommand( ExampleSimpleCommand );
addSubCommand( ThirdAsyncCommand );
addSubCommand( ExampleSimpleCommand );
}

}

If FirstAsyncCommand is going to call ProxyA.1. How would I know when to call commandComplete in FirstAsyncCommand if ProxyA.1 is an async remote object call? I think I need to call commandComplete() before the next SubCommand will execute. (is this right?)

This is taken from the demo just as a reference:
:
public class FirstAsyncCommand extends AsyncCommand
{
/**
* Execute the business logic.
* <P>
* Starts a timer which calls <code>onTimer</code> when complete.
*/
override public function execute ( note:INotification ) : void
{
var timer:Timer = new Timer( 5000, 1 );
timer.addEventListener( TimerEvent.TIMER, onTimer );

var logMessage:String = "STARTING FIRST ASYNC COMMAND...";
sendNotification( ApplicationFacade.LOG_OUTPUT, logMessage );

timer.start();
}

/**
* Handle Timer event.
* <P>
* Resets timer and removes listener, sends a notification
* with a log message and finally, notifies any
* AsyncMacroCommand that may have invoked it that this
* AsyncCommand is complete.
*/
private function onTimer( event:TimerEvent ) : void
{
var t:Timer = event.currentTarget as Timer;
t.reset();
t.removeEventListener( TimerEvent.TIMER, onTimer );
t = null;

var logMessage:String = "FIRST ASYNC COMMAND COMPLETE";
sendNotification( ApplicationFacade.LOG_OUTPUT, logMessage );

commandComplete(); 
}
}

Thanks for your help and I am reading through the other method you suggested.
Shinan


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: puremvc on October 27, 2012, 02:16:00
That's the issue, is getting called back by the Proxy.

The AsyncCommand needs to be set up, for example, as an IResponder and placed in an AsyncToken.responders on the service call or in some other way arrange to be called back when the service is complete.

I don't like Commands getting that closely involved in the service implementation. IResponder and AsyncToken are Flex service classes - what if you wanted to do this with pure AS3? Changing the service implementation shouldn't affect the application's business logic.

My example above, using a ServiceRequest class that extends Observer, keeps it all in-framework and provides the best way I've found to have a Command make an async request and be called back.


Title: Re: AsyncCommand - A PureMVC / AS3 Utility
Post by: skasssam on October 29, 2012, 05:24:22
Thanks Cliff,
I saw what you did in the example and it makes sense. Thanks! That is the methodology I am going to use.