Я не вижу встроенного способа сделать это.
Тем не менее, это определенно возможно реализовать самостоятельно.
Просто создайте класс транзакции, представляющий каждый вызов, который вы делаете с экземпляром NetConnection.
Этот класс транзакции, например «NetTransaction», должен хранить закрытый статический список всех активных транзакций и должен хранить функцию обработчика результатов в закрытой переменной экземпляра, которая должна вызываться по завершении транзакции (в результате, в статус или по тайм-ауту). Обратите внимание, что этот обработчик унифицирован, поэтому он обрабатывает все виды результатов (успех / ошибка / тайм-аут / отменен).
В конструкторе вашего класса транзакций добавьте новый экземпляр «this» в список активных транзакций, запустите таймер тайм-аута, если указан ненулевой тайм-аут (добавление прослушивателя событий, указывающего на функцию cancelTransaction, описанную ниже), а затем выполните последний вызов сети.
Когда вы завершите транзакцию (успех / ошибка / тайм-аут / отменена), удалите ее из списка активных транзакций, отмените таймер тайм-аута, если он был установлен, и, наконец, перенаправьте значимый результат в функцию-обработчик результатов.
Хитрость в том, чтобы заставить все это работать, состоит в том, что вы должны создать функции обработчика результата и состояния в классе транзакции и передать ЭТО свой вызов в NetConnection. Эти две функции будут отвечать за перехват сетевого результата (результат или состояние), завершение транзакции (как описано выше) и пересылку унифицированного результата в функцию-обработчик РЕАЛЬНОГО результата, которая была передана конструктору.
Вот урезанные внутренние части базового класса NetTransaction с базовыми потребностями. В моей реализации есть больше вещей, в том числе создание идентификаторов транзакций (простой статический счетчик, метод поиска активной транзакции по номеру идентификатора. Она также имеет переопределяемые методы 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.
Прелесть этой настройки в том, что теперь, независимо от того, какая ошибка произошла, включая тайм-ауты, ваш ВСЕГДА будет вызываться ваш обработчик результатов для транзакции со всей информацией, необходимой для обработки результата (success / error / timeout /) отменен). Это делает использование объекта NetConnection почти таким же простым и надежным, как и вызов локальной функции!