Updates to the AS3 DataManager

A customer of mine found a bug my AS3 DataManager when making multiple simultaneous calls.  Here is the fix to the bug.

The issue is that while the DataManager allows calls to many methods in a web service, each instance of the DataManager only has a single eventName property.  I was able to work around this by making use of hte AsyncToken, which is returned whenever a call to an AbstractOperation (such as a WebService) is made.  The AsyncToken is carried along with the request and available when results happen as part of the ResultEvent.  Even better, its a dynamic class, so you can add any arbitrary properties on it you want.  So, to fix the issue, replace the existing makeRemoteCall method with this:

public function makeRemoteCall(methodName:String,eventName:String, args:Object):void{
 trace("DataManager.makeRemoteCall("+methodName+","+eventName+","+args+")");
 this.eventName = eventName;
 var op:mx.rpc.AbstractOperation = ws[methodName];
 ws.addEventListener("result",doResults);
 ws.addEventListener("fault",doFault);
 
 if(args){
  op.arguments = args;
 }
 
 var token:AsyncToken = op.send();
 token.eventName = eventName;
}
private function doResults(event:ResultEvent):void{
 var e:DataManagerResultEvent = new DataManagerResultEvent( event.token.eventName, event.result);
 this.dispatchEvent(e);
}

Now, the event names is stored with the request, so we have access to a different event name for each request made!  The completed code looks like this:


package managers {
  import flash.events.EventDispatcher;
  import mx.rpc.soap.WebService;
  import mx.rpc.events.ResultEvent;
  import mx.rpc.events.FaultEvent;
  import mx.rpc.AbstractOperation;
  import events.DataManagerResultEvent;
  import flash.util.*
  import mx.rpc.AsyncToken;;
  /**  DataManager - singleton class which enforces only
  a single object is created for eachwsdl.  To
  access DataManager, use getDataManager(wsdl:String) */
  public class DataManager extends EventDispatcher {
  private var ws:WebService;
  private var eventName:String;
  // hashmap of instances for each wsdl 
  private static var instanceMap:Object = new Object();
  private static var methodEventMap:Object = new Object();
  public function DataManager(pri:PrivateClass, wsdl:String){
   this.ws = new WebService();
   ws.wsdl = wsdl;
   ws.loadWSDL();
   ws.useProxy = false;
  }
  public static function getDataManager(wsdl:String):DataManager{
   if(DataManager.instanceMap[wsdl] == null){
    DataManager.instanceMap[wsdl] = new DataManager(new PrivateClass(),wsdl);
   }
   
   var dm:DataManager= DataManager.instanceMap[wsdl];
   
   if(dm.ws.canLoadWSDL()){
    return dm;
   } else {
    throw new Error("BAD WSDL:"+wsdl);
   }
  }
  
  public function makeRemoteCall(methodName:String,eventName:String, args:Object):void{
   trace("DataManager.makeRemoteCall("+methodName+","+eventName+","+args+")");
   this.eventName = eventName;
   var op:mx.rpc.AbstractOperation = ws[methodName];
   ws.addEventListener("result",doResults);
   ws.addEventListener("fault",doFault);
   
   if(args){
    op.arguments = args;
   }
   
   var token:AsyncToken = op.send();
   token.eventName = eventName;
  }
  
  private function doResults(event:ResultEvent):void{
   var e:DataManagerResultEvent = new DataManagerResultEvent( event.token.eventName, event.result);
   this.dispatchEvent(e);
  }
  
  private function doFault(fault:FaultEvent):void{
   trace("DataManager.doFault("+fault.fault.faultString+")");
   this.dispatchEvent(fault);
  }
  
  public override function toString():String{
   return "DataManager";
  }
 }
}
 /**  PrivateClass is used to make   DataManager constructor private */
class PrivateClass{
 public function PrivateClass() {
 }
}
 

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
BlogCFC was created by Raymond Camden. This blog is running version 5.9.001.