2009-08-06 64 views

回答

0

不是真的。除非你編寫了自己的功能,在指定的時間後中止使用Timer對象(或更好的,如果你不知道GCSafeTimer對象,那麼可以谷歌它)。

1

我沒有看到一個內置的方式做到這一點。 但是,絕對可以自行實施。

只需創建一個事務類代表每個調用您對NetConnection實例。

此事務類(例如「NetTransaction」)應該保留所有活動事務的私有靜態列表,並應將結果處理函數存儲在事務完成時要調用的私有實例變量中(結果上,打開狀態或超時)。請注意,此處理程序是統一的,因此它處理各種結果(成功/錯誤/超時/取消)。

在您的事務類的構造函數中,將「this」新實例添加到活動事務列表中,如果指定了非零超時,則啓動超時計時器(添加指向下面描述的cancelTransaction函數的事件偵聽器),然後最後執行網絡通話。

當您完成交易(成功/錯誤/超時/取消),從活動事務列表中刪除,取消超時定時器,如果一個設置,終於邁出了有意義的結果,以結果處理函數。

訣竅使這一切工作,你必須在交易類中創建的結果和狀態處理功能,並且這些信息傳遞給您的來電的NetConnection。這兩個函數將負責攔截網絡結果(結果或狀態),完成事務(如上所述),並將統一結果轉發給傳遞給構造函數的REAL結果處理函數。

這裏的基礎NetTransaction類的基本必需品剝離下來的內部。我的實現有更多的東西,包括生成事務id(只是一個簡單的靜態計數器,一種通過id號查找活動事務的方法,它也具有可重寫的事務數據對象的get/set方法,所以我可以使用自動頭包裝從NetTransaction(如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))); 
} 

的NetTransactionResult和NetTransactionResultStatus類是我已經設置了類型安全的結果只是簡單的數據類將被髮送到一個統一的結果處理函數,如果NetTransactionResult具有非空狀態屬性,則將結果解釋爲錯誤,否則將結果解釋爲成功並使用包含的數據。您看到的NetworkService類只是一個包裝器四捨五入處理指定調用路徑的NetConnection類,並處理所有低級NetConnection錯誤事件,打包與NetTransaction類兼容的狀態消息,最後調用cancelAllTransactions。

這個設置的好處在於,無論發生什麼樣的錯誤,包括超時,事務的結果處理程序都將始終被調用,並具有處理結果所需的所有信息(成功/錯誤/超時/取消)。這使得使用NetConnection對象幾乎與調用本地函數一樣簡單可靠!