2009-08-06 9 views

Antwort

0

Nicht wirklich. Wenn Sie nicht nach Ablauf einer bestimmten Zeit Ihre eigenen Funktionen zum Abbrechen erstellen, verwenden Sie ein Timer-Objekt (oder besser ein GCSafeTimer-Objekt, wenn Sie das nicht kennen, googlen Sie es).

1

Ich sehe keine eingebaute Möglichkeit, es zu tun. Es ist jedoch durchaus möglich, selbständig zu implementieren.

Erstellen Sie einfach eine Transaktionsklasse für jeden Aufruf einer NetConnection-Instanz.

Diese Transaktionsklasse, z. B. "NetTransaction", sollte eine private statische Liste aller aktiven Transaktionen enthalten und die Ergebnishandlerfunktion in einer privaten Instanzvariablen speichern, die beim Abschluss einer Transaktion aufgerufen werden soll. auf Status oder auf Timeout). Beachten Sie, dass dieser Handler vereinheitlicht ist und alle Arten von Ergebnissen behandelt (Erfolg/Fehler/Timeout/abgebrochen).

Fügen Sie im Konstruktor der Transaktionsklasse "diese" neue Instanz zur Liste der aktiven Transaktionen hinzu, starten Sie einen Zeitüberschreitungstimer, wenn ein Zeitlimit ungleich null angegeben ist (Hinzufügen eines Ereignislisteners, der auf die unten beschriebene Funktion cancelTransaction verweist) Führen Sie den Netzwerkanruf zuletzt aus.

Wenn Sie eine Transaktion abschließen (Erfolg/Fehler/Timeout/abgebrochen), entfernen Sie sie aus der Liste der aktiven Transaktionen, brechen Sie den Timeout-Timer ab und leiten Sie schließlich ein aussagekräftiges Ergebnis an die Ergebnisbehandlungsfunktion weiter.

Der Trick, dies alles zu machen, ist, dass Sie Ergebnis- und Statushandlerfunktionen in der Transaktionsklasse erstellen und THOSE an Ihren Aufruf von NetConnection übergeben müssen. Diese zwei Funktionen sind verantwortlich für das INTERCEPTIEREN des Netzwerkergebnisses (Ergebnis oder Status), das Abschließen der Transaktion (wie oben beschrieben) und das Weiterleiten eines vereinheitlichten Ergebnisses an die REAL-Ergebnisbehandlungsfunktion, die an den Konstruktor übergeben wurde.

Hier ist das abgespeckte Innere der Basis NetTransaction-Klasse mit den grundlegenden Notwendigkeiten. Meine Implementierung enthält mehr Dinge, einschließlich der Generierung von Transaktions-IDs (nur ein einfacher statischer Zähler, eine Methode zum Nachschlagen einer aktiven Transaktion nach ID-Nummer). Außerdem verfügt sie über überschreibbare Methoden für das Datenobjekt der Transaktion/Abwickeln für Klassen benutzerdefinierte Datenprotokolle in von NetTransaction abzuleiten (zB WidgetNetTransaction).

static private var active_transactions:Array = new Array(); //active network requests pending a result 
static private var transaction_count:int = 0; //incremented each time a NetTransaction instance is created so each one can have a unique transaction id number assigned to it 

private var transaction_id:int; //Transaction identifier, which may assist a widget in managing its own concurrent transactions. It comes from a static field, auto-incremented in the NetTransaction constructor, so it is always unique for each NetTransaction within the current session... unless more than 2147483648 transactions occur in a single session and the value wraps around, but by then, old transactions wil be forgotten and there shouldn't be any problems as a result. 
private var description:String; //an optional description string to describe the transaction or what it is supposed to do (especially for error-reporting purposes). 
private var request_data:Object; //this stores the data that will be forwarded to your web server 
private var result_handler:Function; //this is the method to be called after intercepting a result or status event. it's left public, because it's acceptable to modifiy it mid-transaction, although I can't think of a good reason to ever do so 
private var internal_responder:Responder; //internal responder attached to the transaction 
private var timeout:int; 
private var timeout_timer:Timer; 

//Constructor 
public function NetTransaction(network_service:NetworkService, request_data:Object, result_handler:Function = null, description:String = null, timeout:int = 0) 
{ 
    //Throw something a little more friendly than a null-reference error. 
    if (network_service == null) 
     throw new ArgumentError("A NetworkService object must be specified for all NetTransaction objects."); 
    if (timeout < 0) 
     throw new ArgumentError("Timeout must be 0 (infinite) or greater to specify the number of milliseconds after which the transaction should be cancelled.\rBe sure to give the transaction enough time to complete normally."); 

    //Save information related to the transaction 
    this.result_handler = result_handler; 
    this.request_data = request_data; 
    this.internal_responder = new Responder(net_result, net_status); //should use override versions of these methods 
    this.description = description; 
    this.timeout = timeout; 
    this.timeout_timer = null; 

    //Grab a new transaction id, add the transaction to the list of active transactions, set up a timeout timer, and finally call the service method. 
    this.transaction_id = transaction_count++; 
    active_transactions.push(this); //transaction is now registered; this is done BEFORE setting the timeout, and before actually sending it out on the network 
    if (timeout > 0) //zero, represents an infinite timeout, so we'll only create and start a timer if there is a non-zero timeout specified 
    { 
     timeout_timer = new Timer(timeout, 1); 
     timeout_timer.addEventListener(TimerEvent.TIMER, this.cancelTransaction, false, 0, true); 
     timeout_timer.start(); 
    } 
    network_service.call(internal_responder, request_data); 
} 


//Finalizes a transaction by removing it from the active transactions list, and returns true. 
//Returns false to indicate that the transaction was already complete, and was not found in the active transactions list. 
private function completeTransaction():Boolean 
{ 
    var index:int = active_transactions.indexOf(this); 
    if (index > -1) 
    { 
     active_transactions.splice(index, 1); 
     if (timeout_timer != null) 
     { 
      timeout_timer.stop(); 
      timeout_timer.removeEventListener(TimerEvent.TIMER, this.cancelTransaction, false); 
     } 
     return true; 
    } 
    else 
    { 
     //Transaction being removed was already completed or was cancelled 
     return false; 
    } 
} 

//An instance version of the static NetTransaction.cancelTransaction function, which automatically passes the transaction instance. 
public function cancelTransaction(details_status_object:Object = null) 
{ 
    NetTransaction.cancelTransaction(this, details_status_object); 
} 

//Cancels all active transactions immediately, forcing all pending transactions to complete immediately with a "NetTransaction.Call.Cancelled" status code. 
static public function cancelAllActiveTransactions(details_status_object:Object) 
{ 
    for each (var transaction:NetTransaction in active_transactions) 
     transaction.cancelTransaction(details_status_object); 
} 

//Cancels the transaction by spoofing an error result object to the net_status callback. 
static public function cancelTransaction(transaction:NetTransaction, details_status_object:Object) 
{ 
    //Build cancel event status object, containing somewhat standard properties [code,level,description,details,type]. 
    var status:NetTransactionResultStatus = new NetTransactionResultStatus(
     "NetTransaction.Call.Cancelled", 
     "error", //cancelling a transaction makes it incomplete, so the status level should be "error" 
     "A network transaction was cancelled. The description given for the transaction was: " + transaction.description, 
     details_status_object, //include, in the details, the status object passed to this method 
     "" //no type specified 
    ); 
    //Call the net_status handler directly, passing a dynamic Object-typed version of the NetTransactionResultStatus to the net_status handler. 
    transaction.net_status(status.ToObject()); 
} 

//Result responder. Override, then call when you're ready to respond to pre-process the object returned to the result_handler. 
protected function net_result(result_object:Object):void 
{ 
    if (completeTransaction()) 
     if (result_handler != null) 
      result_handler.call(null, new NetTransactionResult(this, result_object, null)); 
} 

//Status responder. Override, then call when you're ready to respond to pre-process the object returned to the result_handler. 
protected function net_status(status_object:Object):void 
{ 
    if (completeTransaction()) 
     if (result_handler != null) 
      result_handler.call(null, new NetTransactionResult(this, null, NetTransactionResultStatus.FromObject(status_object))); 
} 

Die NetTransactionResult und NetTransactionResultStatus Klassen nur einfache Datenklassen sind ich für typsichere Ergebnisse eingerichtet haben zu einem einheitlichen Ergebnis gesendet werden soll Handler-Funktion.Er interpretiert Ergebnisse als einen Fehler, wenn das NetTransactionResult eine Nicht-Null-Statuseigenschaft hat, andernfalls interpretiert es das Ergebnis als Erfolg und verwendet die enthaltenen Daten.Die NetworkService-Klasse, die Sie sehen, ist nur ein Wrapper a um die NetConnection-Klasse herum, die das Angeben des Aufrufpfads behandelt, und behandelt auch alle NetConnection-Fehlerereignisse auf niedriger Ebene, verpackt Statusmeldungen, die mit der NetTransaction-Klasse kompatibel sind, und ruft schließlich cancelAllTransactions auf.

Das Schöne an diesem Setup ist, dass jetzt unabhängig davon, welche Art von Fehler auftritt, einschließlich Timeouts, Ihr Ergebnishandler für eine Transaktion IMMER mit allen Informationen aufgerufen wird, um das Ergebnis zu verarbeiten (Erfolg/Fehler/Timeout) /abgebrochen). Dies macht die Verwendung des NetConnection-Objekts fast so einfach und zuverlässig wie das Aufrufen einer lokalen Funktion!

Verwandte Themen