Lorsque vous utilisez un objet fournisseur de données asynchrone, la propriété
isAsync
d’IFilePromise doit être définie sur
true
et l’objet renvoyé par la méthode
open()
doit implémenter l’interface IEventDispatcher. Le moteur d’exécution écoute plusieurs événements, permettant ainsi d’utiliser divers objets intégrés en tant que fournisseurs de données. Les événements
progress
sont, par exemple, distribués par les objets FileStream et URLStream, alors que les événements
socketData
sont distribués par les objets Socket. Le moteur d’exécution écoute les événements appropriés qui émanent de tous ces objets.
Les événements suivants étayent le processus de lecture des données à partir de l’objet fournisseur de données :
-
Event.OPEN — Indique au moteur d’exécution que la source de données est prête.
-
ProgressEvent.PROGRESS — Indique au moteur d’exécution que les données sont disponibles. Le moteur d’exécution lit le volume de données disponibles dans l’objet fournisseur de données.
-
ProgressEvent.SOCKET_DATA — Indique au moteur d’exécution que les données sont disponibles. L’événement
socketData
est distribué par les objets basés sur un socket. Pour les autres types d’objets, distribuez un événement
progress
. (Le moteur d’exécution écoute les deux événements pour savoir quand les données peuvent être lues.)
-
Event.COMPLETE — Indique au moteur d’exécution que la lecture des données est terminée.
-
Event.CLOSE — Indique au moteur d’exécution que la lecture des données est terminée. (A ce titre, le moteur d’exécution écoute les événements
close
et
complete
.)
-
IOErrorEvent.IOERROR — Indique au moteur d’exécution qu’il s’est produit une erreur lors de la lecture des données. Le moteur d’exécution abandonne la création de fichier et appelle la méthode
close()
d’IFilePromise.
-
SecurityErrorEvent.SECURITY_ERROR — Indique au moteur d’exécution qu’il s’est produit une erreur liée à la sécurité. Le moteur d’exécution abandonne la création de fichier et appelle la méthode
close()
d’IFilePromise.
-
HTTPStatusEvent.HTTP_STATUS — Utilisé en conjonction avec
httpResponseStatus
par le moteur d’exécution pour s’assurer que les données disponibles représentent le contenu requis, plutôt qu’un message d’erreur (une page 404, par exemple). Les objets basés sur le protocole HTTP doivent distribuer cet événement.
-
HTTPStatusEvent.HTTP_RESPONSE_STATUS — Utilisé en conjonction avec
httpStatus
par le moteur d’exécution pour s’assurer que les données disponibles représentent le contenu requis. Les objets basés sur le protocole HTTP doivent distribuer cet événement.
Le fournisseur de données doit distribuer ces événements dans l’ordre suivant :
-
événement
open
-
événements
progress
ou
socketData
-
événement
complete
ou
close
Remarque :
les objets intégrés, FileStream, Socket et URLStream, distribuent automatiquement les événements appropriés.
L’exemple suivant crée un fichier promis en faisant appel à un fournisseur de données asynchrone personnalisé. La classe du fournisseur de données constitue une extension de ByteArray (pour la prise en charge d’IDataInput) et implémente l’interface IEventDispatcher. A chaque événement associé à l’horloge, l’objet génère un bloc de données et distribue un événement « progress » pour avertir le moteur d’exécution que les données sont disponibles. Lorsque le volume de données produit est suffisant, l’objet distribue un événement « 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 );
}
}
}
Remarque :
puisque la classe AsyncDataProvider utilisée dans l’exemple constitue une extension de ByteArray, elle ne peut pas étendre également EventDispatcher. Pour implémenter l’interface IEventDispatcher, la classe fait appel à un objet EventDispatcher interne et transmet à ce dernier les appels de la méthode IEventDispatcher. Vous pouvez également étendre EventDispatcher et implémenter IDataInput (voire implémenter les deux interfaces).
L’implémentation asynchrone d’IFilePromise est quasiment identique à l’implémentation synchrone, à quelques différences près :
isAsync
renvoie
true
et la méthode
open()
renvoie un objet de données asynchrone :
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 );
}
}
}