Chaining Startup Commands/Services
Hi there,
i just switched to RL2. Normally in an app i have to perform
some tasks on startup in an ordered sequence (e.g. Determine the
correct locale, login at the server, ...). For each task i have a
command which just invokes a corresponding service which does the
actual work.
Now my questions:
1) How can the chaining of these ordered commands/services be
performed, i.e. which RL component will receive the finished
notification signals of every service and decide what to do next
(invoke another command or inform the mediator which shows the
first screen) ?
2) I don't think it's a good idea if every service knows about
the next step in the mentioned startup sequence, although it would
probably work with an injected state VO which holds a flag about
the current application state (e.g. "startup", ...).
The better way is in my opinion if every service just dispatches a
notify signal after finishing its work and with that it stays
independent and can also be used as a single service, if
needed.
I would be very interested how you'd implement such a startup chaining behaviour with RL 2 and above all which component acts as the coordinator. Thank you very much.
Best regards
valley
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
Support Staff 1 Posted by Ondina D.F. on 12 Mar, 2014 10:09 AM
Hi Valley,
You're right, services shouldn't have to know about the flow of your loading process or the state of your app.
Exactly.
I'll give you a list of utilities/ extensions that may be of use to you:
DirectCommandMap:
https://github.com/robotlegs/robotlegs-framework/tree/master/src/ro...
Macro command utility for Robotlegs 2 which provides the ability to execute batches of commands in sequential or parallel fashion:
https://github.com/alebianco/robotlegs-utilities-macrobot
AS3StateMachine:
https://github.com/AS3StateMachine
DeferredCommandQueue:
https://github.com/DavidWhittingham/robotlegs-utilities-DeferredCom...
https://github.com/DavidWhittingham/robotlegs-extensions-SignalStat...
SignalResponder:
https://github.com/creynders/SignalResponder
https://github.com/creynders/RelaxedSignalsDemo
Bootstrap:
https://github.com/creynders/robotlegs-demo-bootstrap
Promises:
https://github.com/darscan/robotlegs-extensions-Oil
http://knowledge.robotlegs.org/discussions/questions/115-using-the-...
There are more discussions on this topic on this forum. Search for 'Promises'.
https://github.com/jonnyreeves/as3-async
https://github.com/CodeCatalyst/promise-as3
https://gist.github.com/darscan/4519372
Ondina
2 Posted by rivella50 on 13 Mar, 2014 08:04 AM
Great, thank you Ondina.
I will have a look at the projects you mentioned.
Hopefully there are some approaches which support chaining commands AND
the combination of a command which invokes a service...
valley
Support Staff 3 Posted by creynders on 14 Mar, 2014 12:46 PM
Hey Valley,
Macrobot does exactly what you want, it allows creating command chains. You can mix and match synced and async operations as you please.
For more complex flows I'd definitely recommend a state machine.
4 Posted by rivella50 on 14 Mar, 2014 09:08 PM
Hi creynders,
with RL2 and Macrobot i would use AsyncCommand's to perform stuff like login at a remote server or download some data, and not that the command invokes a service which does that work ? Or how would that work properly, with a callback proxy ?
And do i understand it correctly that an AsyncCommand handles the detain/release part transparently and i only need to implement the listeners and the final complete dispatch signal ?
Thank you.
valley
Support Staff 5 Posted by creynders on 15 Mar, 2014 07:14 AM
No, the asynccomand calls the service and listens to its completion. Then it dispatches its complete event.
Something like this:
That's all there is to it really. Personally I use signals or promises for messaging from services to commands and only use events for system-wide messaging. But the service could also dispatch a system event in which case you don't let the command listen to the service directly but to the injected eventDispatcher.
6 Posted by rivella50 on 16 Mar, 2014 07:54 PM
Works like a charm, thank you very much, creynders!
and in the command:I'm using the signal approach to let the command get notified about the completed service.
Since i mapped the service as follows i had to cast the interface to the service class for getting access to the signal in the command, but this should be no problem i guess:
Support Staff 7 Posted by creynders on 16 Mar, 2014 09:38 PM
I wouldn't upcast, but rather add a getter for the signal to the iface.
On Sunday, March 16, 2014, valley <
[email blocked]> wrote:
Support Staff 8 Posted by creynders on 17 Mar, 2014 10:50 AM
Hey Vallye,
I'll expand a little on why I wouldn't upcast. Upcasting is always a bit fishy and a code smell (except in a few very rare cases). The problem is that you couple the command tightly to the concrete service class, which means that if you need to swap service classes you'll need to update your command as well. On top of that if the original service class remains in the code base and you forgot to update the command, then this will not generate a CTE, but only fails at run-time. Potentially pretty dangerous.
There's a few approaches you can take:
1/ Drop the interface and map the concrete service instead. Least preferable.
2/ Add a getter for the signal to the interface and concrete service class.
3/ Extend the original interface in a new interface which exposes a getter to the signal and use this new interface instead.
I'd definitely go with 2/ in almost all cases. It's one of the benefits of signals that you can add your messaging mechanism to your interface. I'd only use 3 if I'm using an application-specific wrapper for a more generic interface/class.
9 Posted by rivella50 on 17 Mar, 2014 07:14 PM
Ok, i think you are right, thank you for your thoughts.
I will choose one of points 2) and 3) for my concrete app.
Regards
valley
10 Posted by rivella50 on 25 Mar, 2014 09:35 PM
Now i just ran into an error which i couldn't solve quickly.
the offered signal to the command stays there as well.Let's say we have an authentication mechanism with a command and a related service, where the command registers to be notified on the service's complete action.
Since the service is handled as a Singleton with
Now if the command runs several times it registers again and again as a listener for that complete signal and will be notified more than once when the command is invoked several times:
Therefore i'm removing now all listeners for the service signal in function onCompleteService with:
I'm not sure if this is the best way to do this, but now it works fine.
Another possibility could be not to use Singleton services but services which will be instantiated again on every new run?
Support Staff 11 Posted by creynders on 26 Mar, 2014 06:38 AM
Another approach would be to use addOnce: authenticateService.
getNotifyCommandSignal().addOnce(onCompleteService);
Ondina D.F. closed this discussion on 28 Apr, 2014 08:13 AM.