Waiting for a file to be loaded in Actionscript 3 - actionscript-3

I am reading files from disc that have information I need to display to the user. I set up an event listener that flags when the file is loaded- that's easy. However, that adds a delay before I can display the information, and it appears that doing a simple loop in the main code to wait for the file to be loaded does not work:
while (fileComplete == false);
Essentially that simply freezes the code- the file does not load while that loop functions. I can add a timer that checks every few milliseconds to see if fileComplete == true, but I'm wondering if there is a better way. Ideas?

Flash is by default single-threaded, this means if you're initiating an asynchronous process, you need to release the code flow for Flash engine to actually complete the process. Doing an infinite loop like yours does NOT release the code flow, so you should drop this idea. Instead, you should either blindly wait for Event.COMPLETE event and do the post-load actions in the listener, or you should listen for Event.ENTER_FRAME and check for the flag you're setting in Event.COMPLETE listener. The former approach is cleaner.

Related

Stream events: finish vs end

How do I know which event to listen to?
For example gulp.dest fires the finish event and then somewhat later the end event. Some other streams only fire the finish event. When I have a method that returns a stream (could be a read or write stream) and I execute the method, how can I wait for the returned stream to be finished? When do I have to register for the finish and when for the end event?
The gulp.dest object is a Transform object - it handles reading from the (piped) source and writing to the destination. The 'end' event is emitted by the reader, while the 'finish' event is emitted by the writer.
If you are interested in ensuring the reading completes correctly, use .on('end'). See: https://nodejs.org/api/stream.html#stream_event_end.
Readable streams will emit this once data has been completely consumed by the stream. So there may be cases when it doesn't fire, due to the internal logic of the transformation or to an error condition.
If it is the completion of the writing you are interested in, then use .on('finish') instead. See: https://nodejs.org/api/stream.html#stream_event_finish.
Writable streams will emit this after data has been flushed to the underlying system. So in cases where expected read errors are handled, or where the transformation ends the reading early, this event should still be fired. As I understand it, this won't fire if the writing fails unexpectedly.

setTimeout not the same as this.async?

Sometimes I'm coding in a wrong way my polymer 1.0 web app and stuff stops to work properly. Like setting data to some custom element and then immediately trying to read some data out of it (that depends on the data just set) (because I don't know better). Sometimes this doesn't work. Most of the time this.async will help me out, but sometimes it will not. However, setTimeout has never ever failed me in these kind of situations. Most of the time calling setTimeout without providing wait time will work just as well.
For a long time I thought that this.async(function(){...}) is the same as setTimeout(function(){...}). Because sometimes code inside this.async will fail to see changes in custom element's data while code inside setTimeout will not.
Are these two methods are implemented in different way?
this.async adds your function to the start of the event queue, while setTimeout adds it to the end. If you use setTimeout other functions may have been executed before your function is called, causing the changes that you can see in your data.
From the documentation of this.async:
If no wait time is specified, runs tasks with microtask timing (after the current method finishes, but before the next event from the event queue is processed)
setTimeout on the other hand will add your function to the end of the queue as is described in the section "Adding Messages" of this article.
Calling setTimeout will add a message to the queue after the time passed as second argument. If there is no other message in the queue, the message is processed right away; however, if there are messages, the setTimeout message will have to wait for other messages to be processed. For that reason the second argument indicates a minimum time and not a guaranteed time

Should I remove listener for SOUND_COMPLETE event?

My application needs to notify UI that sound playback is finished. To accomplish that is attaches listener to the SOUND_COMPLETE event of a SoundChannel object.
Should I remove my SOUND_COMPLETE event listener after event processing is done?
private function playbackCompleteHandler(event:Event):void {
// Notify UI that playback is done etc
channel.removeEventListener(Event.SOUND_COMPLETE, playbackCompleteHandler);
}
Everyone says that we should always remove event listeners so that GC could properly collect objects ('channel' object in this case). But it seems that Adobe doesn't do that in the official documentation [1][2]
[1] http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/SoundChannel.html
[2] http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7d21.html
Dispatcher holds listeners, so, if your dispatcher is long-living(like Application), you should use weak listeners:
channel.removeEventListener(Event.SOUND_COMPLETE, playbackCompleteHandler,false,0, true)
last true allows your objects to be freed.
If you don't need your temporary objects to process dispatcher's events after you loose all references to temporary objects and until they are collected, you shall remove listeners
Otherwise(when dispatchers are short-living), there is no need to care about listeners: if you are listening to something temporary, it will die without any problems.
It seems that your case is the last one, so it's better not to pollute code with meaningless lines.
You're question states my answer for this
Everyone says that we should always remove event listeners so that GC
could properly collect objects
If you are no longer keeping an instance of the Sound object around; then remove the event listener. If you will still be using the Sound object; then there is no need to remove the listener.

as3 air unloadAndStop() event listener or timer

my air application plays an external swf over and over until time to play the next external swf. in order to avoid memory leaks i am using unloadAndStop(). i am using two timers. the first unloadAndStops the swf. the second waits two seconds then loads it back up again.
this approach (coupled with the use of weak references) seems to keep the memory in check. however, i'd rather not use timers but event listeners. is there an event listener for when unloadAndStop completes to then load the swf again.
here is what i had in mind:
var TIMER_INTERVAL:int = int(duration);
var t:Timer = new Timer(TIMER_INTERVAL);
t.addEventListener(TimerEvent.TIMER,updateTimer,false,0,true);
t.start();
private function updateTimer(e:TimerEvent):void
{
swfLoader.unloadAndStop(true);
swfLoader.addEventListener(Event.UNLOAD,onSWFUnloadComplete,false,0,true);
}
private function updateTimer(e:TimerEvent):void
{
var swfSource2:String = File.applicationStorageDirectory.nativePath.toString();
swfLoader.load(swfSource2+'\\'+name_xml);
}
unloadAndStop is not an asynchronous method, so an unload event wouldn't really be relevant. What is likely happening behind the scenes is that it takes 1 full frame to fully dispose of the movies objects/listeners and that's why you're having issues loading it again in the same block of code.
If you wait just one frame before loading it again, you should have the results you expect.
Now, of course the best solution is go into the source file of your loaded swf and fix the memory leaks.

Is Event TIMER always dispatched before TIMER_COMPLETE?

Is flash.utils.Timer object's event TIMER always dispatched before TIMER_COMPLETE?
During the 2nd event, I am nullifying stuff that are required during the 1st event; so their order is of prime importance. I checked the docs and there is no guarantee for their dispatching order.
In tests I've done it seems that this is the case, but I don't want to distribute publicly software without confirming first.
You can avoid this problem by using TimerEvent.TIMER only:
private function onTimer(event:TimerEvent)
{
// ...
if (timer.currentCount == timer.repeatCount) {
// timer is complete
}
}
I'm almost positive this is the case, since the code seems to be in the player itself I don't think you can get at the source to get a legitimate confirmation, however I have always seen this to be the case myself and from how the docs read it sounds as though a TIMER event would always be dispatched before the complete event
timerComplete
Dispatched whenever it has completed the number of requests set by Timer.repeatCount.
timer
Dispatched whenever a Timer object reaches an interval specified according to the Timer.delay property.
So I imagine the timerComplete is dispatched after it receives enough timer events that the currentCount equals the repeat count then a timerComplete is dispatched, however without being able to look at the code it's impossible for anyone to completely confirm this. Possibly you could look at the Gnash source to see how it's handled by that implementation of the player, but it's not necessarily the same in the normal Flash Player.