Ao usar um objeto de fornecedor de dados assíncrono, a propriedade
isAsync
do IFilePromise deve ser
true
e o objeto devolvido pelo método
open()
deve implementar a interface IEventDispatcher. O tempo de execução ouve os vários eventos alternativos de forma que se possam usar objetos incorporados diferentes como fornecedor de dados. Por exemplo, os eventos
progress
são despachados pelos objetos FileStream e URLStream, ao passo que os eventos
socketData
são despachados pelos objetos Socket. O tempo de execução ouve os eventos apropriados de todos esses objetos.
Os eventos a seguir orientam o processo de leitura de dados do objeto do fornecedor de dados:
-
Event.OPEN — Informa ao tempo de execução que a fonte de dados está pronta.
-
ProgressEvent.PROGRESS — Informa ao tempo de execução que os dados estão disponíveis. O tempo de execução vai ler a quantidade de dados disponíveis do objeto do fornecedor de dados.
-
ProgressEvent.SOCKET_DATA — Informa ao tempo de execução que os dados estão disponíveis. O evento
socketData
é despachado pelos objetos baseados em soquete. Para os outros tipos de objeto, despache um evento
progress
. (O tempo de execução ouve os dois eventos para detectar quando os dados podem ser lidos.)
-
Event.COMPLETE — Informa ao tempo de execução que os dados foram todos lidos.
-
Event.CLOSE — Informa ao tempo de execução que os dados foram todos lidos. (O tempo de execução ouve
close
e
complete
para essa finalidade.)
-
IOErrorEvent.IOERROR — Informa ao tempo de execução que ocorreu um erro ao ler os dados. O tempo de execução aborta a criação do arquivo e chama o método
close()
do IFilePromise.
-
SecurityErrorEvent.SECURITY_ERROR — Informa ao tempo de execução que ocorreu um erro de segurança. O tempo de execução aborta a criação do arquivo e chama o método
close()
do IFilePromise.
-
HTTPStatusEvent.HTTP_STATUS — Usado, junto com
httpResponseStatus
, pelo tempo de execução para garantir que os dados disponíveis representem o conteúdo desejado, em vez de uma mensagem de erro (como uma página 404). Os objetos baseados no protocolo HTTP devem despachar esse evento.
-
HTTPStatusEvent.HTTP_RESPONSE_STATUS — Usado, junto com
httpStatus
, pelo tempo de execução para garantir que os dados disponíveis representam o conteúdo desejado. Os objetos baseados no protocolo HTTP devem despachar esse evento.
O fornecedor de dados deve despachar esses eventos na sequência a seguir:
-
evento
open
-
Eventos
progress
ou
socketData
-
Evento
complete
ou
close
Nota:
Os objetos incorporados, FileStream, Socket e URLStream, despacham os eventos apropriados automaticamente.
O exemplo a seguir cria uma promessa de arquivo usando um fornecedor de dados personalizado e assíncrono. A classe do fornecedor de dados estende ByteArray (para o suporte do IDataInput) e implementa a interface IEventDispatcher. No evento de cada cronômetro, o objeto gera um pouco de dados e despacha um evento progress para informar ao tempo de execução que os dados estão disponíveis. Quando forem produzidos dados suficientes, o objeto despacha um evento completo.
package
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.utils.ByteArray;
import flash.utils.Timer;
[Event(name="open", type="flash.events.Event.OPEN")]
[Event(name="complete", type="flash.events.Event.COMPLETE")]
[Event(name="progress", type="flash.events.ProgressEvent")]
[Event(name="ioError", type="flash.events.IOErrorEvent")]
[Event(name="securityError", type="flash.events.SecurityErrorEvent")]
public class AsyncDataProvider extends ByteArray implements IEventDispatcher
{
private var dispatcher:EventDispatcher = new EventDispatcher();
public var fileSize:int = 0; //The number of characters in the file
private const chunkSize:int = 1000; //Amount of data written per event
private var dispatchDataTimer:Timer = new Timer( 100 );
private var opened:Boolean = false;
public function AsyncDataProvider()
{
super();
dispatchDataTimer.addEventListener( TimerEvent.TIMER, generateData );
}
public function begin():void{
dispatchDataTimer.start();
}
public function end():void
{
dispatchDataTimer.stop();
}
private function generateData( event:Event ):void
{
if( !opened )
{
var open:Event = new Event( Event.OPEN );
dispatchEvent( open );
opened = true;
}
else if( position + chunkSize < fileSize )
{
for( var i:int = 0; i <= chunkSize; i++ )
{
writeUTFBytes( 'A' );
}
//Set position back to the start of the new data
this.position -= chunkSize;
var progress:ProgressEvent =
new ProgressEvent( ProgressEvent.PROGRESS, false, false, bytesAvailable, bytesAvailable + chunkSize);
dispatchEvent( progress )
}
else
{
var complete:Event = new Event( Event.COMPLETE );
dispatchEvent( complete );
}
}
//IEventDispatcher implementation
public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
{
dispatcher.addEventListener( type, listener, useCapture, priority, useWeakReference );
}
public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void
{
dispatcher.removeEventListener( type, listener, useCapture );
}
public function dispatchEvent(event:Event):Boolean
{
return dispatcher.dispatchEvent( event );
}
public function hasEventListener(type:String):Boolean
{
return dispatcher.hasEventListener( type );
}
public function willTrigger(type:String):Boolean
{
return dispatcher.willTrigger( type );
}
}
}
Nota:
Como a classe AsyncDataProvider no exemplo estende ByteArray, ela não pode estender também o EventDispatcher. Para implementar a interface IEventDispatcher, a classe usa um objeto EventDispatcher interno e encaminha as chamadas do método IEventDispatcher para aquele objeto interno. Você também poderia estender o EventDispatcher e implementar IDataInput (ou implementar as duas interfaces).
A implementação assíncrona de IFilePromise é quase idêntica à implementação síncrona. As principais diferenças são que
isAsync
retorna
true
e que o método
open()
retorna um objeto de dados assíncrono:
package
{
import flash.desktop.IFilePromise;
import flash.events.ErrorEvent;
import flash.events.EventDispatcher;
import flash.utils.IDataInput;
public class AsynchronousFilePromise extends EventDispatcher implements IFilePromise
{
private var fileGenerator:AsyncDataProvider;
private const fileSize:int = 5000; //size of file data
private var filePath:String = "AsynchronousFile.txt";
public function get relativePath():String
{
return filePath;
}
public function get isAsync():Boolean
{
return true;
}
public function open():IDataInput
{
fileGenerator = new AsyncDataProvider();
fileGenerator.fileSize = fileSize;
fileGenerator.begin();
return fileGenerator;
}
public function close():void
{
fileGenerator.end();
}
public function reportError(e:ErrorEvent):void
{
trace("Something went wrong: " + e.errorID + " - " + e.type + ", " + e.text );
}
}
}