Quando utilizzate un oggetto fornitore di dati asincrono, la proprietà
isAsync
di IFilePromise deve essere impostata su
true
e l'oggetto restituito dal metodo
open()
deve implementare l'interfaccia IEventDispatcher. Il runtime intercetta eventi alternativi in modo da poter utilizzare oggetti incorporati diversi come fornitore di dati. Ad esempio, gli eventi
progress
vengono inviati dagli oggetti FileStream e URLStream, mentre gli eventi
socketData
vengono inviati da oggetti Socket. Il runtime intercetta gli eventi appropriati da tutti questi oggetti.
Gli eventi seguenti guidano il processo di lettura dei dati dall'oggetto fornitore di dati:
-
Event.OPEN: informa il runtime che l'origine dati è pronta.
-
ProgressEvent.PROGRESS: informa il runtime che i dati sono disponibili. Il runtime legge la quantità di dati disponibile dall'oggetto fornitore di dati.
-
ProgressEvent.SOCKET_DATA: informa il runtime che i dati sono disponibili. L'evento
socketData
viene inviato da oggetti basati su socket. Per altri tipi di oggetti, dovete inviare un evento
progress
. (Il runtime intercetta entrambi gli eventi per rilevare quando è possibile leggere i dati.)
-
Event.COMPLETE: informa il runtime che tutti i dati sono stati letti.
-
Event.CLOSE: informa il runtime che tutti i dati sono stati letti. (Per questa ragione, il runtime intercetta entrambi gli eventi
close
e
complete
.)
-
IOErrorEvent.IOERROR: informa il runtime che si è verificato un errore di lettura dei dati. Il runtime arresta la creazione del file e chiama il metodo
close()
di IFilePromise.
-
SecurityErrorEvent.SECURITY_ERROR: informa il runtime che si è verificato un errore di sicurezza. Il runtime arresta la creazione del file e chiama il metodo
close()
di IFilePromise.
-
HTTPStatusEvent.HTTP_STATUS: utilizzato dal runtime, insieme a
httpResponseStatus
, per essere certi che i dati disponibili rappresentino il contenuto desiderato, piuttosto che un messaggio di errore (ad esempio, una pagina 404). Gli oggetti basati sul protocollo HTTP devono inviare questo evento.
-
HTTPStatusEvent.HTTP_RESPONSE_STATUS: utilizzato dal runtime insieme a
httpStatus
per essere certi che i dati disponibili rappresentino il contenuto desiderato. Gli oggetti basati sul protocollo HTTP devono inviare questo evento.
Il fornitore di dati deve inviare questi eventi nella sequenza seguente:
-
evento open
-
Evento
progress
o
socketData
-
Evento
complete
o
close
Nota:
gli oggetti incorporati, FileStream, Socket e URLStream, inviano gli eventi appropriati automaticamente.
Nell'esempio seguente viene creata una promessa di file utilizzando un fornitore di dati asincrono personalizzato. La classe del fornitore di dati estende ByteArray (per il supporto IDataInput) e implementa l'interfaccia IEventDispatcher. A ogni evento del timer, l'oggetto genera una porzione di dati e invia un evento progress per informare il runtime che i dati sono disponibili. Quando è stato prodotto un numero di dati sufficiente, l'oggetto invia un evento complete.
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:
poiché la classe AsyncDataProvider nell'esempio estende ByteArray, non può estendere anche EventDispatcher. Per implementare l'interfaccia IEventDispatcher, la classe utilizza un oggetto EventDispatcher interno e inoltra le chiamate al metodo IEventDispatcher a tale oggetto. Potete anche estendere EventDispatcher e implementare IDataInput (o implementare entrambe le interfacce).
L'implementazione IFilePromise asincrona è quasi identica a quella sincrona. Le differenze principali sono che
isAsync
restituisce
true
e che il metodo
open()
restituisce un oggetto dati asincrono:
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 );
}
}
}