Using the AsyncCommand with services, callbacks?

Jos Yule's Avatar

Jos Yule

30 Mar, 2010 04:16 PM via web

Hello all.

I've just started a new project, and have taken advantage of Shawn's AsyncCommand class (http://gist.github.com/302698). I am, however, wondering how best to use it when calling services. Do you use a callback method? How do you "re-enter" the command when the service is done doing its thing?

Any suggestions, examples or pointers to code would be most welcome!

Thanks!
jos

  1. Support Staff 2 Posted by Shaun Smith on 31 Mar, 2010 01:27 PM

    Shaun Smith's Avatar

    Hi Jos,

    There is no way to "re-enter" these commands unfortunately; AsyncCommands become responsible for themselves, and need to explicitly call finish() internally to be released.

    In general, the concept of a dedicated Service and the concept of an asynchronous Command are orthogonal. AsyncCommands are useful when you don't have a dedicated Service to perform the work. Perhaps for some unique process that will only ever occur once but takes some time to complete.

    I have a generic RemoteService that I inject into any AsyncCommand that needs to perform a remote operation. Any operation on this service will return a Promise (see: http://en.wikipedia.org/wiki/Promise_%28programming%29 ). Callbacks can then be added to the promise. It looks something like this:

    remoteService.get('/sessions/current')
        .addResultHandler(onCurrentSessionResult)
        .addFaultHandler(onCurrentSessionFault);
    

    I realized the other day however that I don't really need to be using AsyncCommands when dealing with Promises, as the service will keep the commands alive by way of the callbacks in any case. Still, an AsyncCommand would be necessary if the command itself had the only reference to the remote service.

  2. 3 Posted by Jos Yule on 01 Apr, 2010 02:12 PM

    Jos Yule's Avatar

    Thanks for the reply.

    I used "re-enter" poorly - i was talking about using callbacks from the service call, to "re-enter" the async-command. I see that with your promise, you do the same, and, as you point out, don't even need the asyncCommand in this case.

    I like the idea of a generic RemoteService, which, i'm guessing, simply returns the contents of whatever it is sent to load. This puts all the logic into the command, rather then having a set of services for each data type/file you need to load (or however you break out your classes).

    Thanks for the answer, i will continue to ponder the ins and outs of OOP/DI/IoC architecture.

  3. 4 Posted by Nikos Katsikanis on 19 Aug, 2010 09:57 AM

    Nikos Katsikanis's Avatar

    So the async-command really is to be prevent GC on the local service being called?

    not realy sure what this does?

    _commands[this] = true;

    :)

  4. Support Staff 5 Posted by Shaun Smith on 19 Aug, 2010 11:59 AM

    Shaun Smith's Avatar

    That line pins the Command in memory (not the service). That AsyncCommand is no longer needed in Robotlegs v1.1.2 however. The CommandMap has detain() and release() methods that can hold command instances for you. So, you'd just use a normal command, and do something like this:

    override public function execute():void
    {
        commandMap.detain(this);
        // and then kick off some async process...
    }
    
    private function onSomethingHappened():void
    {
        commandMap.release(this);
    }
    
  5. 6 Posted by Nikos Katsikanis on 19 Aug, 2010 12:05 PM

    Nikos Katsikanis's Avatar

    excellent news, that means we can use promise in commands :)
    Does promise use Async token?

  6. 7 Posted by Nikos Katsikanis on 19 Aug, 2010 12:07 PM

    Nikos Katsikanis's Avatar

    hmm appears not

  7. Support Staff 8 Posted by Shaun Smith on 19 Aug, 2010 12:21 PM

    Shaun Smith's Avatar

    Nikos, see this post:

    http://knowledge.robotlegs.org/discussions/questions/215-parallel-s...

    Promises can certainly be used from Commands - even without using detain/release() - as the Service that handed out the Promise will (indirectly) keep a reference to the Command. So long as the Service is mapped as Singleton, or is being held by something else.

  8. Support Staff 9 Posted by Shaun Smith on 19 Aug, 2010 12:23 PM

    Shaun Smith's Avatar

    Ah, no, my Promise does not make use of Flex's AsyncToken so that it can be used in pure AS3 projects.

  9. 10 Posted by Nikos Katsikanis on 19 Aug, 2010 12:28 PM

    Nikos Katsikanis's Avatar

    so what use is promise now that we have detain()?

  10. Support Staff 11 Posted by Shaun Smith on 19 Aug, 2010 12:41 PM

    Shaun Smith's Avatar

    CommandMap.detain() is used to hold a command instance in memory to prevent GC while some async process occurs.

    A Promise is a concept/pattern:

    "In computer science, future, promise, and delay refer to constructs used for synchronization in some concurrent programming languages. They describe an object that acts as a proxy for a result that is initially not known, usually because the computation of its value has not yet completed." - http://en.wikipedia.org/wiki/Futures_and_promises

    My AS3 implementation of the Promise pattern ( http://gist.github.com/470851 ) allows me to bind to results that are "initially not known".

  11. 12 Posted by iki_xx on 08 Sep, 2010 10:28 PM

    iki_xx's Avatar

    Shaun , can you explain your AS3 implementation of the promise pattern on gist?
    Maybe even a little tutorial on your blog? :)
    I understand the concept of the "Asynchronous Token/ Promise pattern", but it's a little hard to digest the version with the "results that are initially unknown "
    Thanks !

  12. Support Staff 13 Posted by Shaun Smith on 08 Sep, 2010 11:20 PM

    Shaun Smith's Avatar

    Hi,

    I don't want to blog about it until I'm happier with the implementation (which needs some work). Usage might look something like this:

    // Direct binding
    myComponent.dataSource = myService.get("/user/a786b67e").result;
    

    The call to get returns a Promise. Every promise has a bindable result property.

    Here's the same thing with some handlers:

    // With callbacks
    myComponent.dataSource = myService.get("/user/a786b67e")
        .addResultHandler(resultHandler)
        .addFaultHandler(faultHandler)
        .result;
    
    function resultHandler(promise:Promise):void
    {
        myComponent.dataSource = promise.result;
    }
    
    function faultHandler(promise:Promise):void
    {
        myComponent.error = promise.fault;
    }
    

    An unlimited number of result and fault handlers can be attached to any Promise.

    Hope that helps!

  13. 14 Posted by Nikos Katsikanis on 15 Oct, 2010 01:31 PM

    Nikos Katsikanis's Avatar

    Could he still accomplish a similar thing (just simple fault + response callback)without the promise as I've not got my head round it yet :)

  14. Stray closed this discussion on 13 Feb, 2011 03:00 PM.

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