비동기 데이터 공급자 객체를 사용하는 경우에는 IFilePromise
isAsync
속성이
true
여야 하며
open()
메서드로 반환되는 객체에서 IEventDispatcher 인터페이스를 구현해야 합니다. 런타임에서는 여러 기본 제공 객체를 데이터 공급자로 사용할 수 있도록 몇 가지 대체 이벤트를 수신합니다. 예를 들어
progress
이벤트는 FileStream 및 URLStream 객체에 의해 전달되지만
socketData
이벤트는 Socket 객체에 의해 전달됩니다. 런타임에서는 이러한 모든 객체로부터 적합한 이벤트를 수신합니다.
다음 이벤트는 데이터 공급자 객체에서 데이터를 읽는 프로세스를 구동합니다.
-
Event.OPEN - 데이터 소스가 준비되었음을 런타임에 알립니다.
-
ProgressEvent.PROGRESS - 데이터를 사용할 수 있음을 런타임에 알립니다. 런타임에서 데이터 공급자 객체로부터 사용 가능한 데이터 양을 읽습니다.
-
ProgressEvent.SOCKET_DATA - 데이터를 사용할 수 있음을 런타임에 알립니다.
socketData
이벤트는 소켓 기반 객체에 의해 전달됩니다. 다른 객체 유형의 경우
progress
이벤트를 전달해야 합니다. 런타임에서 두 이벤트를 모두 수신하여 데이터를 읽을 수 있는 경우를 감지합니다.
-
Event.COMPLETE - 데이터를 모두 읽었음을 런타임에 알립니다.
-
Event.CLOSE - 데이터를 모두 읽었음을 런타임에 알립니다. 이를 위해 런타임에서
close
및
complete
를 모두 수신합니다.
-
IOErrorEvent.IOERROR - 데이터를 읽는 동안 오류가 발생했음을 런타임에 알립니다. 런타임에서 파일 만들기를 중단하고 IFilePromise
close()
메서드를 호출합니다.
-
SecurityErrorEvent.SECURITY_ERROR - 보안 오류가 발생했음을 런타임에 알립니다. 런타임에서 파일 만들기를 중단하고 IFilePromise
close()
메서드를 호출합니다.
-
HTTPStatusEvent.HTTP_STATUS - 사용 가능한 데이터가 오류 메시지(예: 404 페이지)가 아니라 원하는 내용을 나타내도록 하기 위해
httpResponseStatus
와 함께 런타임에서 사용됩니다. HTTP 프로토콜 기반 객체는 이 이벤트를 전달해야 합니다.
-
HTTPStatusEvent.HTTP_RESPONSE_STATUS - 사용 가능한 데이터가 원하는 내용을 나타내도록 하기 위해
httpStatus
와 함께 런타임에서 사용됩니다. HTTP 프로토콜 기반 객체는 이 이벤트를 전달해야 합니다.
데이터 공급자는 다음과 같은 순서로 이러한 이벤트를 전달해야 합니다.
-
open 이벤트
-
progress
또는
socketData
이벤트
-
complete
또는
close
이벤트
참고:
기본 제공 객체 FileStream, Socket 및 URLStream은 적합한 이벤트를 자동으로 전달합니다.
다음 예제에서는 사용자 정의 비동기 데이터 공급자를 사용하여 파일 프로미스를 만듭니다. 데이터 공급자 클래스는 ByteArray(IDataInput 지원)를 확장하고 IEventDispatcher 인터페이스를 구현합니다. 각 타이머 이벤트에서 객체는 데이터 청크를 생성하고 데이터를 사용할 수 있음을 런타임에 알리기 위해 progress 이벤트를 전달합니다. 충분한 데이터가 생성되면 객체가 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 );
}
}
}
참고:
예제에서 AsyncDataProvider 클래스는 ByteArray를 확장하므로 EventDispatcher도 확장할 수 없습니다. IEventDispatcher 인터페이스를 구현하기 위해 클래스에서는 내부 EventDispatcher 객체를 사용하고 IEventDispatcher 메서드 호출을 해당 내부 객체에 전달합니다. 또한 EventDispatcher를 확장하고 IDataInput(또는 두 인터페이스 모두)를 구현할 수 있습니다.
비동기 IFilePromise 구현은 동기 구현과 거의 동일합니다. 주요 차이점은
isAsync
는
true
를 반환하고,
open()
메서드는 비동기 데이터 객체를 반환한다는 것입니다.
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 );
}
}
}