Optimizing Data Communication


When you work with data, it is frequently important that you optimize the manner in which you work with the data. The following sections look at several specific ways you can optimize your work with data.

Caching Data

When an application makes calls to services, it is typically either submitting or requesting data. When an application requests data, there are two ways it can use that data: temporarily or persistently. If the data is used temporarily, it can and should be discarded when the application no longer needs it. However, when the data is used persistently, it can sometimes be useful to store that data in a persistent data model rather than discarding it and re-requesting it when the application needs the data again.

The technique of caching persistent data allows you to minimize the number of requests made to the server when the same data is used over and over. The sample limerick application is a good case in point. The application uses just a handful of pieces of data. The implementation thus far makes requests for each limerick every time the data is needed by the application. If the application displays one of the limericks fifty times, it also makes a request for the data fifty times from the server. Yet the cost of making those network requests is expensive, both in terms of bandwidth usage and latency in the application. In this particular case, a better solution is to store the limerick data client-side rather than making the request to the server each time.

There are two ways you can handle retrieving persistent data: requesting all the data at once or requesting the data one piece at a time as the user needs it, but caching the data rather than discarding it. The first technique has the advantage of ensuring the immediate availability of data when the user requests it. Yet the first technique also requires a potentially large initial download, even though the user may or may not be using all the data. The second technique allows the application to download data only when it is first requested by the user. Which technique you select depends on the requirements for the application. If the application allows for an initial wait for the user but requires low latency and immediate responsiveness after that initial wait, then you should download the data as part of an initialization. If the data set is very large and the average user of the application is not likely to use all the data every time she uses the application, it is generally better to download data on demand and cache it for later use.

We'll look at how to rewrite the LimerickData class so that it uses the on-demand techniquecaching data so the class doesn't have to download the same data twice. For this purpose, we'll introduce a new class called LimerickItem. This class is a simple data model for a single limerick that stores the limerick text and its index.

package com.peachpit.aas3wdp.limerickreader.data {    import flash.events.EventDispatcher;    import flash.events.Event; public class LimerickItem extends EventDispatcher {    private var _index:uint;    private var _text:String;    public function LimerickItem(index:uint) {       _index = index;    }    public function getIndex():uint {       return _index;    }         public function getText():String {       return _text;    }    public function setText(value:String):void {       _text = value;       dispatchEvent(new Event(Event.CHANGE));    }   } }


Next, modify the existing LimerickData class so that it stores LimerickItem objects in an array. When the application requests a limerick that's already been loaded, the data model returns the cached data rather than request it from the server again.

package com.peachpit.aas3wdp.limerickreader.data {    import flash.events.EventDispatcher;    import flash.events.Event;    import flash.net.NetConnection;    import flash.net.Responder;        public class LimerickData extends EventDispatcher {       private var _limerick:String;       private var _ids:Array;       private var _pendingNext:Boolean;       private var _netConnection:NetConnection;       private var _limericks:Array;       public function get limerick():String {          return _limerick;       }       public function LimerickData() {          _limerick = "";          _netConnection = new NetConnection();          _netConnection.connect("http://localhost/limerick/gateway.php");          _netConnection.call("LimerickService.getIds", new Responder(setIds, null));          // This is the array in which the model stores each          // of the LimerickItem objects.          _limericks = new Array();        }        private function setIds(ids:Array):void {           _ids = ids;           if(_pendingNext) {              next();           }        }        public function next():void {          if(_ids != null) {            var index:uint = _ids[Math.floor(Math.random() * _ids.length)];            // Test if the data has already been            // requested. If not, request it. If so,            // set current limerick to the cached            // value.            if(_limericks[index] == undefined) {               var item:LimerickItem = new LimerickItem(index);               // Listen for the change event that               // the item dispatches when the value               // is set, and then call onItem().               item.addEventListener(Event.CHANGE, onItem);               _limericks[index] = item;               // Use item.setText as the result                // event handler method.               netConnection.call("LimerickService.getLimerick", new Responder               (item.setText, null), index, false);             }             else{                 onData(_limericks[index].getText());             }           }           else {              _pendingNext = true;           }          }         // When the data is returned and assigned to the limerick         // item, then call onData() wuith the data.         private function onItem(event:Event):void {            onData(event.target.getText());         }         private function onData(limerick:String):void {             _limerick = limerick;             dispatchEvent(new Event(Event.CHANGE));         }              }     }


Queuing and Pooling Requests

When you have lots of service calls, there are two ways you can call them: back to back, or all together. The back-to-back technique is what we call queuing. The technique of calling all the methods at once is what we call pooling. Each has advantages and disadvantages.

A novice approach to remote procedure calls is to simply make the calls when it's convenient. This approach means that some calls are queued and some calls are pooled, but never intentionally. This is not generally a good approach because there are cases in which calls must be queued and cases in which it is better if they are pooled. It is better to specifically select the manner in which you make service method calls.

The limerick application has a perfect example of a case in which method calls must be queued. Two service methods are called in the example: getIds() and getLimerick(). It is essential that getIds() is called before getLimerick() because getLimerick() requires a parameter whose value is determined by the result of the getIds() method call. This means you must queue the method calls to ensure that getIds() returns a value before getLimerick() is called. In the existing example, this order is achieved by using an if statement to test that the _ids array (which is populated by the return value from getIds()) is defined before calling getLimerick().

Pooling requests is rarely if ever required. However, pooling does significantly reduce network overhead. If there are several method calls that do not have dependencies (which would require that they be queued), and if those methods are likely to be called in relatively close succession anyway, it is better to make the requests all at the same time. Flash Player automatically bundles together all requests made in the same frame (which basically amounts to all requests made in the same routine) into a single AMF request packet.




Advanced ActionScript 3 with Design Patterns
Advanced ActionScript 3 with Design Patterns
ISBN: 0321426568
EAN: 2147483647
Year: 2004
Pages: 132

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net