Notifying async command from another command

Mr.Newb's Avatar

Mr.Newb

15 Aug, 2012 02:46 PM

Hello Robotlegs folks,

I am using Macrobot utility to execute a sequence of commands. One of the commands triggers a quite large sub-task (it involves user interaction). At this point I want to suspend the sequence until the sub-task is complete. I am using a callback function (wrapped into CallbackProxy for sake of injection) to notify CommandA from CommandB that the sub-task has been completed (see code excerpt below).

I would like to hear your opinion of this. Might there be a better way to achieve this?

public class CommandA extends AsyncCommand {
    [Inject]
    public var callbackProxy:CallbackProxy;

    override public function execute():void {
        super.execute();            
        callbackProxy.registerCallback(this.callback);            
    }

    private function callback(result:Boolean):void {
        dispatchComplete(result);
    }
}

public class CommandB extends Command {
    [Inject]
    public var callbackProxy:CallbackProxy;

    override public function execute():void {       
        var result:Boolean = getResult();
        callbackProxy.notify(result);
    }
}
  1. Support Staff 2 Posted by Ondina D.F. on 16 Aug, 2012 05:03 PM

    Ondina D.F.'s Avatar

    Hey Mr. Newb,

    So, let’s see if I understand the workflow..thinking out loud:
    CommandA is part of a sequence mapped in SomeMacroCommand.
    In CommandA you doSomething() (the user interaction thing).
    Maybe it’s a Mediator that’s dispatching an event (let’s call it runSubTask just for the sake of an example) that triggers CommandB (which is a normal command).
    CommandB is accessing a Service (your CallbackProxy). When the Service is done, you want CommandA to doAnotherthing() and then dispatchComplete so other Commands will run as mapped in your MacroCommand. Correct?

    Your CommandA as I understand it:

    
    public class CommandA extends AsyncCommand
    {
        [Inject]
        public var callbackProxy:CallbackProxy;
            
        override public function execute():void
        {
            callbackProxy.registerCallback(this.callback);
            doSomething();
            //dispatched somewhere else:
            //dispatch(new Event("runSubTask"));
        }       
        private function doSomething():void
        {
            //dispatch an event ->Mediator->View                
        }
        private function callback(result:Boolean):void
        {
            doAnotherthing();
            dispatchComplete(result);
        }
        private function doAnotherthing():void
        {               
        }       
    }
    

    What I would do (theoretically) :
    I would let CommandA doSomething() and then dispatchComplete(true);
    If the mentioned Mediator would dispatch new Event("runSubTask"), or a better named custom event, it would trigger CommandB. CommandB could register the callback function or use other ways to detain the command, and when the Service returns the results, CommandB could dispatch an event triggering AnotherMacroCommand where you’d have the mappings for the following commands, if need be. One of them would be CommandC that would doAnotherthing();
    In this scenario you don’t need CallbackProxy
    and a callback in your CommandA, which would have just the responsabilty of doingSomething ;)

    I don’t know if this is a practicable solution for you, or if it’s better than yours. Hopefully you’ll get feedback from other users too.
    Your solution might work, but without trying it out, I can’t say for sure if your commands would really run in the order of the mappings, or if the response from the Service will come at a later time than expected, due to the asynchronous nature of a Service.

    Ondina

  2. 3 Posted by Mr.Newb on 17 Aug, 2012 08:54 AM

    Mr.Newb's Avatar

    Thanks for the response Ondina.

    Yes, CommandA is a part of a sequence. The only purpose of CommandA is to register a callback and trigger a sub-task, and than wait until it will be notified via the callback. Depending on the result from the callback sequence will either continue or abort.

    What I am trying to achieve by using Macrobot, rather than simple command chaining via events, is to make the process code more readable and easy to understand. Not entirely sure if I am succeeding...

  3. Support Staff 4 Posted by Ondina D.F. on 17 Aug, 2012 01:39 PM

    Ondina D.F.'s Avatar

    What about:
    CommandA.execute()
    eventDispatcher.addEventListener(SomeEvent.SUBTASK_COMPLETED, onSubTaskComplete);//dispatched from SubTask on completion

    dispatch(new SomeEvent (SomeEvent.RUN_SUBTASK));

    CommandA.onSubTaskComplete(…)
    dispatchComplete(true);

    This way you don’t have to inject CallbackProxy into CommandA and to register a callback function with CallbackProxy, and in case you need to make a call to CallbackProxy elsewhere, you don’t need to have conditional statements inside of that proxy concerning the null value of the callback..

    But, on the other hand, I’m curious to hear what’s wrong with having 2 MacroCommands like this:

    1. FirstMacroCommand (SequenceCommand )
      CommandA
      CommandB
      CommandC-> SomeEvent.RUN_SUBTASK ->triggers SubTask

    2. SubTask – if successful->dispatch event (SomeEvent.SUBTASK_COMPLETED) to trigger SecondMacroCommand, else abort

    3. SecondMacroCommand (SequenceCommand )
      CommandD
      CommandE
      ..etc

    Having 2 MacroCommands mapping distinct Commands for distinct actions/functionality is readable and understandable, in my opinion, if you map them like this:

    commandMap.mapEvent(SomeEvent.DO_SOME_CONFIG, FirstMacroCommand);
    commandMap.mapEvent(SomeEvent.SUBTASK_COMPLETED, SecondMacroCommand);

    Ondina

  4. 5 Posted by Mr.Newb on 17 Aug, 2012 02:32 PM

    Mr.Newb's Avatar

    That's it! The eventDispatcher. How stupid of me not to see the obvious. I had a feeling that I am overthinking this. :)

    I want to reuse the sub-task in a number of different workflows, so I was thinking that it could be more convenient to allow the "main task" to wait for sub-task to complete, rather than delegate triggering the next action to the sub-task.

    Thanks a lot Ondina.

  5. Support Staff 6 Posted by Ondina D.F. on 17 Aug, 2012 02:47 PM

    Ondina D.F.'s Avatar

    Oh, cool! I’m really glad that our discussion resulted in a solution that works out well for you :)

    I’m closing the thread now.
    Feel free to re-open it, if need be.

    Cheers,
    Ondina

  6. Ondina D.F. closed this discussion on 17 Aug, 2012 02:47 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac