Handling asynchronous calls to services

Because ActionScript code executes asynchronously, if you allow concurrent calls to a service, you must ensure that your code handles the results appropriately, based on the context in which the service is called. By default, making a request to a web service operation that is already executing does not cancel the existing request. In a Flex application in which a service can be called from multiple locations, the service might respond differently in different contexts.

When you design a Flex application, consider whether the application requires disparate data sources, and the number of types of services that the application requires. The answers to these questions help determine the level of abstraction that you provide in the data layer of the application.

In a very simple application, user-interface components might call services directly. In applications that are slightly larger, business objects might call services. In still larger applications, business objects might interact with service broker objects that call services.

To understand the results of asynchronous service calls to objects in an application, you need a good understanding of scoping in ActionScript.

Subtopics

Using the Asynchronous Completion Token design pattern
Making a service call when another call is completed

Using the Asynchronous Completion Token design pattern

Flex is a service-oriented framework in which code executes asynchronously, therefore, it lends itself well to the Asynchronous Completion Token (ACT) design pattern. This design pattern efficiently dispatches processing within a client in response to the completion of asynchronous operations that the client invokes. For more information, see www.cs.wustl.edu/~schmidt/PDF/ACT.pdf.

When you use the ACT design pattern, you associate application-specific actions and state with responses that indicate the completion of asynchronous operations. For each asynchronous operation, you create an ACT that identifies the actions and state that are required to process the results of the operation. When the result is returned, you can use its ACT to distinguish it from the results of other asynchronous operations. The client uses the ACT to identify the state required to handle the result.

An ACT for a particular asynchronous operation is created before the operation is called. While the operation is executing, the client continues executing. When the service sends a response, the client uses the ACT that is associated with the response to perform the appropriate actions.

When you call a Flex remote object service, web service, or HTTP service, Flex returns an instance of the service call. When you use the default concurrency value, multiple, you can use the call object that is returned by the data service's send() method to handle the specific results of each concurrent call to the same service. You can add information to this call object when it is returned, and then in a result event listener you can pass back the call object as event.token. This is an implementation of the ACT design pattern that uses the call object of each data service call as an ACT. How you use the ACT design pattern in your own code depends on your requirements. For example, you might attach simple identifiers to individual calls, more complex objects that perform their own set of functionality, or functions that a central listener calls.

The following example shows a simple implementation of the ACT design pattern. This example uses an HTTP service and attaches a simple variable to the call object.

...
<mx:HTTPService id="MyService" destination="httpDest" result="resultHandler(event)"/>
...
<mx:Script>
    <![CDATA[
        ...
        public function storeCall():void {
            // Create a variable called call to store the instance
            // of the service call that is returned.    
            var call:Object = MyService.send();

            // Add a variable to the call object that is returned.
            // You can name this variable whatever you want.
            call.marker = "option1";
            ...
        }

        // In a result event listener, execute conditional
        // logic based on the value of call.marker.
        private function resultHandler(event:ResultEvent):void {
            var call:object = event.token
            if (call.marker == "option1") {
            //do option 1
            }
            else 
            ...
        }
    ]]>
</mx:Script>
...

Making a service call when another call is completed

Another common requirement when using data services is the dependency of one service call on the result of another. Your code must not make the second call until the result of the first call is available. You must make the second service call in the result event listener of the first, as the following example shows:

...
<mx:WebService id="ws" destination="wsDest"...>
  <mx:operation name="getCurrentSales" result="resultHandler(event.result)"/>
  <mx:operation name="setForecastWithSalesInput"/>
</mx:WebService>
<mx:Script>
    <![CDATA[
        // Call the getForecastWithSalesInput operation with the result of the 
        // getCurrentSales operation.
            public function resultHandler(currentsales:String):void {
            ws.setForecastWithSalesInput(currentsales);
            //Or some variation that uses data binding.
            }
    ]]>
</mx:Script>
...

Flex 2.01

Take a survey