tag:robotlegs.tenderapp.com,2009-10-18:/discussions/robotlegs-2/1173-command-with-async-stuff-happeningRobotlegs: Discussion 2013-05-16T09:35:54Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/261009182013-03-27T17:53:17Z2013-03-27T17:53:17ZCommand with async stuff happening<div><p>Hi Matej,</p>
<p>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.</p>
<p>In robotlegs v2 the eventCommandMap doesn’t provide
detain() and release() methods.<br>
That’s Context’s job now.</p>
<p>From inside a command you’d have to access the context and
let it detain the command:</p>
<p>[Inject] public var context:IContext;</p>
<p>public function execute():void<br>
{ context.detain(this); …</p>
<p>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.</p>
<p>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</p>
<p>context.hasDetainedInstance(instance) to check against it in a
guard ....</p>
<p>What I did instead, was using kind of a VO to set a flag on a
running command.<br>
I mapped the command like this:</p>
<pre>
<code>commandMap.map(SomeEvent.LOAD_SOMETHING)
.toCommand(LoadSomethingCommand)
.withGuards(CommandGuard);</code>
</pre>
<p>Flag as VO:</p>
<pre>
<code>private var _commandIsReleased:Boolean=true;
public function CommandFlag()
{
}
public function get commandIsReleased():Boolean
{
return _commandIsReleased;
}
public function set commandIsReleased(value:Boolean):void
{
_commandIsReleased = value;
}</code>
</pre>
<p>Guard: checks if the command is running</p>
<pre>
<code>public class CommandGuard
{
[Inject]
public var commandFlag:CommandFlag;
public function CommandGuard()
{
}
public function approve():Boolean
{
return commandFlag.commandIsReleased;
}
}</code>
</pre>
<p>Command: sets commandFlag.commandIsReleased to false, so another
command won’t be executed while this one is running.</p>
<pre>
<code>[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);
}
}</code>
</pre>
<p>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 :)</p>
<p>Ondina</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/261009182013-03-29T13:05:16Z2013-03-29T13:05:16ZCommand with async stuff happening<div><blockquote>
<p>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.</p>
</blockquote>
<p>I agree. Today I suggested the use of a convenience class to
Shaun to solve this.</p></div>creynderstag:robotlegs.tenderapp.com,2009-10-18:Comment/261009182013-03-29T14:50:24Z2013-03-29T14:50:24ZCommand with async stuff happening<div><blockquote>
<p>Today I suggested the use of a convenience class to Shaun to
solve this.</p>
</blockquote>
<p>Oh, that’s good news:)<br>
Btw., good work on the CommandCenter & Co !</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/261009182013-04-08T10:00:50Z2013-04-08T10:00:50ZCommand with async stuff happening<div><p>@Matej Closing the discussion for now. You can re-open it, if
need be.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/261009182013-04-22T15:47:23Z2013-04-22T17:06:46ZCommand with async stuff happening<div><p>So,</p>
<p>is there any other suggestion for async tweens, timers or ect...
handling inside commands instead of detaining the command?</p>
<p>How are you guys doing it?<br>
:)</p>
<p>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<br></p>
<pre>
<code> execute(){
context.detain
...some listener
}
onComplete(){
code...
context.release
}</code>
</pre>
<p>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.</p></div>matejtag:robotlegs.tenderapp.com,2009-10-18:Comment/261009182013-04-23T09:14:49Z2013-04-23T09:14:49ZCommand with async stuff happening<div><p>TBH I do very little async stuff in commands, since it goes
against their concept.</p>
<p>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.</p></div>creynderstag:robotlegs.tenderapp.com,2009-10-18:Comment/261009182013-04-25T11:41:31Z2013-04-25T11:41:31ZCommand with async stuff happening<div><p>"we could split that command into two, and the model will
dispatch a signal which will call the second part of the command.
"</p>
<p>@matej: In what way does this differ from the usual flow in MVC?
-> Command updates model --> model dispatches event --->
event triggers new command</p>
<p>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".<br>
Maybe you should ask yourself you're doing this in the right
place?</p></div>dotdotcommadottag:robotlegs.tenderapp.com,2009-10-18:Comment/261009182013-05-16T09:35:53Z2013-05-16T09:35:53ZCommand with async stuff happening<div><p>I'm closing this for now, if you have any more questions let us
know!</p></div>creynders