Consider an enterprise application in which a user can place purchase orders for some parts and request price quotes from various suppliers. In this case, the user may click several buttons, resulting in server-side calls to one or more destinations. On each click event of the button, a RemoteObject sends a new request to the server.
The user hits this button several times to place several orders, which in turn initiates the same number of remote calls. The user can also click different buttons, initiating calls to different destinations. Because of the asynchronous nature of remote calls in Flex, the results from each call can arrive at random times.
When each result arrives to the client, it triggers a result event, which obediently calls the result handler function written by an application programmer. So far, so good. Here’s the million-dollar question: how can the application code map arriving result objects back to the initial requesters if they can come back to the client in an arbitrary order? The fact that you place an order to purchase a Sony TV first and a DVD player 10 seconds afterward doesn’t guarantee that results will arrive to your Flex application in the same order.
The goal of the Asynchronous Token pattern is to properly route the processing on the client in response to the data arriving asynchronously from the server. Because AsyncToken is a dynamic class, you can add any properties to this class during runtime, as is done with orderNumber in Example 2-20. You can also add one or more responders that will provide the result handling. Adding responders on the token level simplifies memory management.
Example 2-20. Using the AsyncToken class
...
private function sendOrder(/*arguments go here*/):void{
var token: AsyncToken = ord.placeOrder({item:"Sony TV"});
token.orderNumber="12345";
token.responder = new Responder(processOrderPlaced, processOrderFault);
token.addResponder(new Responder(createShipment,processOrderFault));
}
AsyncToken is a local object. It is identified by a messageId that is passed with the request to the server. When the server responds, it includes a correlationId property in the message header, and Flex automatically calls the appropriate AsyncToken responders in the order they were defined. Example 2-20 calls the function send(), which starts with creating the AsyncToken instance. Then, you'll attach as many properties to this instance as you need. You may get the impression that something is not right�the values are being assigned to the instance of the token after the request has been sent to the server for execution. If so, when the result in the form of an AsyncToken comes back, it shouldn't contain values such as orderNumber and references to the responders, right? Wrong.
Flash Player executes your application’s requests in cycles driven by frame events. First, it performs the requests related to the modifications of the UI, then it gives a slice of time to process the application’s ActionScript code, and only after that does it take care of the network requests, if any. This means that all the code in the previous snippet will complete before the call ord.placeOrder({item:"Sony TV"}) is made. Always remember that from the developer’s perspective, Flex applications are single-threaded and responses are handled within each such cycle—even if the underlying communications are multithreaded.
In Example 2-20 , two responders were added to the placeOrder() request. In the case of successful order placement, two functions will be called: processOrderPlaced() and createShipment(). In the case of errors, the function processOrderFault()will be called.
You can add an instance of a Responder object to a token on the fly, as was done in the earlier code snippet, or your can provide an existing instance of a class that implements the IResponder interface—that is, that has the functions result() and fault().
To see a different way of assigning a responder, please revisit the code in Example 1-6 that demonstrates how Cairngorm’s Delegateclass adds a Command object as a responder. Sure enough, the Command object implements result() and fault() methods.
In the more traditional way of programming client/server communications, you define the handlers for results and faults:
<mx:RemoteObject id="ord" destination="Orders" result="processOrderPlaced(event)" fault="processOrderFault(event)"/>
But using AsyncToken, you can assign the handlers during runtime as was done in Example 2-20 , which gives your application additional flexibility.
At some point in time, the result will come back to the client and you can retrieve the token from the property ResultEvent.token and examine its dynamic properties (just the orderNumber in your case) that were originally added to the token:
private function processOrderPlaced(event:ResultEvent):void {
myOrderNumber:Object = event.token.orderNumber;
// if myOrderNumber is 12345, process it accordingly
}
Using the Asynchronous Token design pattern allows Flex to efficiently map associated requests and responses without the need to introduce a multithreaded environment and create some mapping tables to avoid mixing up requests and responses.