Command with async stuff happening

matej's Avatar

matej

27 Mar, 2013 01:52 PM

Hello,

currently when I have some async listeners in my commands, I do:
context.detain(this);
and onComplete{
context.release(this);
}

Is is possible to make the command map run execute on the same command, if the command is detained and hasn't been released yet?

  1. Support Staff 1 Posted by Ondina D.F. on 27 Mar, 2013 05:53 PM

    Ondina D.F.'s Avatar

    Hi Matej,

    In robotlegs v1 you can trigger and run another instance of the same command even if the first running instance has been detained, as far as I know.

    In robotlegs v2 the eventCommandMap doesn’t provide detain() and release() methods.
    That’s Context’s job now.

    From inside a command you’d have to access the context and let it detain the command:

    [Inject] public var context:IContext;

    public function execute():void
    { context.detain(this); …

    Injecting the context into a command isn’t very nice, in my opinion, but I don’t know of a better/cleaner way to do it.

    To prevent a new instance of a command from running while another instance is already running, it would be cool if we had something like

    context.hasDetainedInstance(instance) to check against it in a guard ....

    What I did instead, was using kind of a VO to set a flag on a running command.
    I mapped the command like this:

    commandMap.map(SomeEvent.LOAD_SOMETHING)
    .toCommand(LoadSomethingCommand)
    .withGuards(CommandGuard);
    

    Flag as VO:

    private var _commandIsReleased:Boolean=true;
            public function CommandFlag()
            {
            }
            public function get commandIsReleased():Boolean
            {
                return _commandIsReleased;
            }
            public function set commandIsReleased(value:Boolean):void
            {
                _commandIsReleased = value;
            }
    

    Guard: checks if the command is running

    public class CommandGuard
    {               
        [Inject]
        public var commandFlag:CommandFlag;
        
        public function CommandGuard()
        {
        }
        public function approve():Boolean
        {           
            return commandFlag.commandIsReleased;
        }
    }
    

    Command: sets commandFlag.commandIsReleased to false, so another command won’t be executed while this one is running.

    [Inject]
    public var commandFlag:CommandFlag;
    
    public function execute():void
    {
            context.detain(this);
            commandFlag.commandIsReleased = false;
            doSomethingAsync();
    }
    private function doSomethingAsync():void
    {
            if(someCondition)
            {
                    commandFlag.commandIsReleased = true;
                    context.release(this);
            }
    }
    

    That works, but I don’t like the solution very much, so, I hope Shaun will chime in as well and show us a more elegant way to detain commands in rl2 :)

    Ondina

  2. Support Staff 2 Posted by creynders on 29 Mar, 2013 01:05 PM

    creynders's Avatar

    Injecting the context into a command isn’t very nice, in my opinion, but I don’t know of a better/cleaner way to do it.

    I agree. Today I suggested the use of a convenience class to Shaun to solve this.

  3. Support Staff 3 Posted by Ondina D.F. on 29 Mar, 2013 02:50 PM

    Ondina D.F.'s Avatar

    Today I suggested the use of a convenience class to Shaun to solve this.

    Oh, that’s good news:)
    Btw., good work on the CommandCenter & Co !

  4. Support Staff 4 Posted by Ondina D.F. on 08 Apr, 2013 10:00 AM

    Ondina D.F.'s Avatar

    @Matej Closing the discussion for now. You can re-open it, if need be.

  5. Ondina D.F. closed this discussion on 08 Apr, 2013 10:00 AM.

  6. matej re-opened this discussion on 22 Apr, 2013 03:47 PM

  7. 5 Posted by matej on 22 Apr, 2013 03:47 PM

    matej's Avatar

    So,

    is there any other suggestion for async tweens, timers or ect... handling inside commands instead of detaining the command?

    How are you guys doing it?
    :)

    I was thinking of one model that will make the async stuff, and once it is over it will call another command. So instead of

        execute(){
        context.detain
        ...some listener
        }
        onComplete(){
        code...
        context.release
        }
    

    we could split that command into two, and the model will dispatch a signal which will call the second part of the command. That way also, we dont have the hanging in the air commands that are not destroyed because the async stuff is taking long.

  8. Support Staff 6 Posted by creynders on 23 Apr, 2013 09:14 AM

    creynders's Avatar

    TBH I do very little async stuff in commands, since it goes against their concept.

    Typically my commands trigger a service call, when that's finished the service dispatches an event which in turn triggers another command. If I need a properly ordered flow I use a state machine to control the flow.

  9. 7 Posted by dotdotcommadot on 25 Apr, 2013 11:41 AM

    dotdotcommadot's Avatar

    "we could split that command into two, and the model will dispatch a signal which will call the second part of the command. "

    @matej: In what way does this differ from the usual flow in MVC? -> Command updates model --> model dispatches event ---> event triggers new command

    Also, I don't know if it's relevant (I know its just an example), but a Tween and a Timer look to me more like view-related components as well.. I can't really think of a situation where these should be used in "business logic".
    Maybe you should ask yourself you're doing this in the right place?

  10. Support Staff 8 Posted by creynders on 16 May, 2013 09:35 AM

    creynders's Avatar

    I'm closing this for now, if you have any more questions let us know!

  11. creynders closed this discussion on 16 May, 2013 09:35 AM.

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