views:

3311

answers:

3

I've been utilizing the command pattern in my Flex projects, with asynchronous callback routes required between:

  • whoever instantiated a given command object and the command object,
  • the command object and the "data access" object (i.e. someone who handles the remote procedure calls over the network to the servers) that the command object calls.

Each of these two callback routes has to be able to be a one-to-one relationship. This is due to the fact that I might have several instances of a given command class running the exact same job at the same time but with slightly different parameters, and I don't want their callbacks getting mixed up. Using events, the default way of handling asynchronicity in AS3, is thus pretty much out since they're inherently based on one-to-many relationships.

Currently I have done this using callback function references with specific kinds of signatures, but I was wondering if someone knew of a better (or an alternative) way?

Here's an example to illustrate my current method:

  • I might have a view object that spawns a DeleteObjectCommand instance due to some user action, passing references to two of its own private member functions (one for success, one for failure: let's say "deleteObjectSuccessHandler()" and "deleteObjectFailureHandler()" in this example) as callback function references to the command class's constructor.
  • Then the command object would repeat this pattern with its connection to the "data access" object.
  • When the RPC over the network has successfully been completed (or has failed), the appropriate callback functions are called, first by the "data access" object and then the command object, so that finally the view object that instantiated the operation in the first place gets notified by having its deleteObjectSuccessHandler() or deleteObjectFailureHandler() called.
+1  A: 

Many of the Flex RPC classes, like RemoteObject, HTTPService, etc. return AsyncTokens when you call them. It sounds like this is what you're after. Basically the AsyncToken encapsulates the pending call, making it possible to register callbacks (in the form of IResponder instances) to a specific call.

In the case of HTTPService, when you call send() an AsyncToken is returned, and you can use this object to track the specific call, unlike the ResultEvent.RESULT, which gets triggered regardless of which call it is (and calls can easily come in in a different order than they were sent).

Theo
This is a good idea in general but in my case I want to handle the "raw" RPC results first in the "data access" object and then pass these handled results on to the caller (the command object), which is why I'm currently using the AsyncTokens to keep the references to the callba
hasseg
+2  A: 

I'll try one more idea:

Have your Data Access Object return their own AsyncTokens (or some other objects that encapsulate a pending call), instead of the AsyncToken that comes from the RPC call. So, in the DAO it would look something like this (this is very sketchy code):

public function deleteThing( id : String ) : DeferredResponse {
    var deferredResponse : DeferredResponse = new DeferredResponse();

    var asyncToken : AsyncToken = theRemoteObject.deleteThing(id);

    var result : Function = function( o : Object ) : void {
        deferredResponse.notifyResultListeners(o);
    }

    var fault : Function = function( o : Object ) : void {
        deferredResponse.notifyFaultListeners(o);
    }

    asyncToken.addResponder(new ClosureResponder(result, fault));

    return localAsyncToken;
}

The DeferredResponse and ClosureResponder classes don't exist, of course. Instead of inventing your own you could use AsyncToken instead of DeferredResponse, but the public version of AsyncToken doesn't seem to have any way of triggering the responders, so you would probably have to subclass it anyway. ClosureResponder is just an implementation of IResponder that can call a function on success or failure.

Anyway, the way the code above does it's business is that it calls an RPC service, creates an object encapsulating the pending call, returns that object, and then when the RPC returns, one of the closures result or fault gets called, and since they still have references to the scope as it was when the RPC call was made, they can trigger the methods on the pending call/deferred response.

In the command it would look something like this:

public function execute( ) : void {
    var deferredResponse : DeferredResponse = dao.deleteThing("3");

    deferredResponse.addEventListener(ResultEvent.RESULT, onResult);
    deferredResponse.addEventListener(FaultEvent.FAULT,   onFault);
}

or, you could repeat the pattern, having the execute method return a deferred response of its own that would get triggered when the deferred response that the command gets from the DAO is triggered.

But. I don't think this is particularly pretty. You could probably do something nicer, less complex and less entangled by using one of the many application frameworks that exist to solve more or less exactly this kind of problem. My suggestion would be Mate.

Theo
A: 

The AbstractCollection is the best way to deal with Persistent Objects in Flex / AIR. The GenericDAO provides the answer.

DAO is the Object which manages to perform CRUD Operation and other Common Operations to be done over a ValueObject ( known as Pojo in Java ). GenericDAO is a reusable DAO class which can be used generically. Goal:

In JAVA IBM GenericDAO, to add a new DAO, the steps to be done is simply, Add a valueobject (pojo). Add a hbm.xml mapping file for the valueobject. Add the 10-line Spring configuration file for the DAO.

Similarly, in AS3 Project Swiz DAO. We want to attain a similar feet of achievement.

Client Side GenericDAO model: As we were working on a Client Side language, also we should be managing a persistent object Collection (for every valueObject) . Usage: Source: http://github.com/nsdevaraj/SwizDAO

nsdevaraj