Actionscript 3 - Does handling an event work separately than a function - actionscript-3

Let's suppose I have some event handlers set, and then I have this loop which is working, if I fire the event, will the function be triggered or will it get stuck?

Flash is, for the most part, single threaded. This means that it can only do one thing at once. (You can use Workers nowadays to get around that, but we'll ignore those for the sake of this answer)
So, events can only fire when there is a gap in execution. If you have a loop running, there won't be such a gap until after that loop, and any additional code, has run.
The answer to your question is it will not run until the loop has finished. And any events that are triggered during code execution are queued and fired in order as soon as a gap in execution occurs.

If you are dispatching events within your loop then your application will respond to them.
If you have a loop that is doing it's own thing and your code that dispatches events is outside of that then your application will not get those events while the loop is occurring.
In the following examples, events will be dispatched:
for (var i:int;i<1000;i++) {
// do something
dispatchEvent(myEvent);
}
...events will not be dispatched:
for (var i:int;i<1000;i++) {
// do something
// no events dispatched while in this loop
}
dispatchEvent(myEvent);
If you are in the for loop too long, AIR or the Flash Player runtime will timeout.
Possibly a better approach would be to use a ActionScript worker as the other poster posted or check the time you've been in the loop and break out of it after a specific amount of time. You would then be breaking your work up into chunks.
var landBeforeTime = getTimer();
for (var i:int;i<1000;i++) {
// do something
// check we aren't taking too long
if (getTimer()-landBeforeTime>1000){
notDone = true;
break;
}
}
if (notDone) {
// come back in the next frame and finish this loop
setTimeout (myForLoop, 100);
}
The previous code is an example. You'll want to use enterFrame and tidy things up.

Related

AS3 - reset delay on Timer

I have a private Timer object in an AS3 Class called _countDownTimer.
When the class is instantiated, I also initialize the Timer once like so with some arbitrary delay
_countDownTimer =new Timer(10000, 1);
_countDownTimer.addEventListener(TimerEvent.TIMER, onCue,false,0,true);
The problem is I need to change the delay time every time the Timer runs.
So in another method I first redefine a private var _newDelayTime and then call startMyTimer() to redefine the delay and start the _countDownTimer.
My question is, should this work properly?
Do I ALSO need to instantiate a NEW _countDownTimer and re-add the listener every time I change the delay?
private function startMyTimer():void{
_countDownTimer.reset();
_countDownTimer.stop();
_countDownTimer.delay=_newDelayTime;
_countDownTimer.start();
}
private function onCue(e:TimerEvent):void{
trace('do stuff');
}
You do not need (or want) to create a whole new timer object.
Setting the delay while the timer is running is perfectly acceptable.
Do note though, that setting the delay resets the timer, as per the documentation:
If you set the delay interval while the timer is running, the timer will restart at the same repeatCount iteration.
So, if the timer doesn't actually need to stop, take off the 1 repeat count when you instantiate (and start it), and then just change the delay whenever you need to.
_countDownTimer.delay=_newDelayTime; //no need to reset/stop/restart
as I know, as3 Timer class is not precise in counting time... it depends on how fast listener function executes (waits until function finishes its job and continues counting). I prefer using greensock... but if it's not so important for you to have precise time than you can do something like this:
private function onCue(e:TimerEvent):void
{
trace(e.currentTarget.delay);
_newDelayTime = Math.round(Math.random() * 999) + 1;
startMyTimer();
trace('do stuff');
}
you can manipulate with _newDelayTime diffenetly... this should work properly and you wont need to re-add listeners

AS3 - stop onEnterFrame Function from constantly running

Okay, I have a collisionTest function that is tied to my "onEnterFrameHandler" function.
So to simplify the way it looks:
onEnterFrameHandler(e:Event):void{
testCollision();
}
testCollision():void{
trace("always running");
if(1_MC.hitTestObject(2_MC)){
//do stuff
}
}
The thing is, it is always running. Constantly running in order to test for a collision. I have a feeling that it is what may be causing the lag on this project.
Do you know of a good way to control a function that needs to be able to check, at any time, an event, yet not run while the even is not occurring?
Usually you are always checking for collisions in a game loop. You provide a flag to indicate if something needs to be checked or not.
On a side note, consider using collision detection kit, I think you'll find it takes care of just about every scenario you can have regarding collisions.
It's hard to answer this question as it is pretty vague when you're not checking for collision. To improve the performance it's not about changing how to collision test, but when to do the check.
so you could do this by simply adding an if statement like so:
if (doCollisionTest){testCollision();}
but that doesn't solve when doCollisionTest is true or false, and that's the tricky part, that cannot be answered from the information you provided.
If you don't need to check every single frame, you can use a Timer to only check as often as you like, for instance, if you deemed it good enough to check 3 times per second, you'd set it up like this:
var timer:Timer = new Timer(333); //run 3 times a second
timer.addEventListneer(TimerEvent.TIMER, collisionTest, false, 0, true);
timer.start();
function collisionTest(e:Event = null):void {
//do you collision stuffs
}
Then, if for whatever reason you want to temporarily disable it, use timer.stop() , then timer.start() again

Does AS3 wait for each line of code in a function to be executed before moving on to the next line?

I am trying to dispatch an event but not sure when I should do it to get the right results. The first event "submitClicked" is in the right spot and works great. However, the second event "dataReady" seems like it might be a problem.
I need it to be dispatched after this.compiledFormData is set.
Does AS3 wait for each line of code in a function to be executed before moving on to the next line?
// --------------------------------------------------------------------
public function submitForm()
{
//dispatch an event
var cEvt:FormRendererEvent = new FormRendererEvent( "submitClicked" );
cEvt.customMessage = "Started Submitting Form Data";
dispatchEvent(cEvt);
this.compiledFormData = JSON.encode(this.compileFormData());
var cEvt:FormRendererEvent = new FormRendererEvent( "dataReady" );
cEvt.customMessage = "Data is ready to be used";
dispatchEvent(cEvt);
}//end function
Yes, in AS3 each line must complete before the next line can run. When you dispatch events though, they will go off and do their own thing. So, your "main" code might complete, meanwhile your dispatched events could still be processing.
Each line of code is executed sequentially yes, but whether the implementation of the invoked API does something asynchronous is dependent on what API you're calling.
In this case JSON.encode is a synchronous operation and therefore will complete fully before the next line of code is executed.

AS3: Run methods in an ordered sequence

I have a class with several methods I must run in an specific order. So, I created a kind of chain where each one calls the next in its last sentence (sometimes with calls, sometimes dispatching events):
internal function a(evt:SwapEvent):void { //started from custom event
...
b();
}
private function b():void {
...
bTimer = new Timer(bTime*1000,1);
bTimer.addEventListener(TimerEvent.TIMER, bEnd);
bTimer.start();
}
private function bEnd(evt:TimerEvent):void {
bTimer.removeEventListener(TimerEvent.TIMER, bEnd);
bTimer = null;
c();
}
private function c():void {
...
dispatchEvent(new CustomEvents(CustomEvents.NEXT_FRAME,1));
}
....
private function g():void {
// tell the second class the sequence finished
}
The problem is at some point and before arriving at last method, I need to run again a sub-sequence, let's say from function c() to e(). And it's causing problems in the form of an increasing delay between functions (I have 2 timers)
I guess the solution is something like this:
a();
b();
...
if (some condition) {
c();
...
e();
}
...
f();
g();
But, as far as I know, Flash Player doesn't make a synchronous execution. i.e., it doesn't wait until method a() completes to execute b()
Any idea/suggestion on a clean and bullet-proof implementation? This application will run in an endless loop 24x7
Thanks in advance,
After reading your code properly, yes, you are right. b() gets executed as that line of code is reached.
I might be tempted to create a queue of methods to execute. Execute one, check to see if you have time to execute another before the frame needs updating, and repeat. You can always insert new commands in to the queue at any time, so b() could insert endB() next in the queue.
Both the sequencers at http://www.dpdk.nl/opensource/running-tasks-in-order-with-a-task-based-sequence-manager and http://as3.casalib.org/docs/org_casalib_time_Sequence.html should do what you need. The former might be a bit of overkill as it looks like you need to create individual classes for each of your tasks which may be a little too much overhead. On the other hand the Conditional Tasks look like they are exactly what you need. The latter being simpler in that you can specify methods to execute. However, there doesn't seem to be a built in way to condition the tasks, but that may just be as easy as creating a task that conditionally adds tasks.
It might help to know a bit more how the conditions work.
Other points:
Tail calls are not very efficient in AS. Think of it as adding more to the stack every time you call a method. Once the method returns (even if you don't explicitly use return) the method gets knocked off the stack and the previously called method will continue to execute. So the more tail calls, the bigger the stack and the more to clean up.
As soon you start executing code the player hangs until the code has completely run and execution has returned to the player. You have around a 15 second execution limit before the player will kill your script, so you have to account for that when endlessly executing code. The solution is to execute some code then wait till the next frame to execute more.
You don't have to recreate your Timers, you can create them once as instance variables and just call start. The timers will return execution to the player (if no more method calls are made).
A somewhat simplified version, but I'm sure you get the picture.
ADDENDUM: I think you should look in to the Command Pattern (http://en.wikipedia.org/wiki/Command_pattern). You can store an array of commands to be executed (either synchronously, or asynchronously) and when one returns or dispatches a complete event you execute the next. I think you can create a simple implementation of the Command Pattern to do what you need without all the overhead of sequencers I mentioned earlier, but it's always good to get an idea of how others have done it.
There are a number of libraries that provide sequenced execution in AS3. Usually they are for performing Animation so they will generally have a bias toward that.
For example, Twease and Tweener will let you do sequenced actions as well as generic animation actions.
Another particularly good sequencing library is included as part of the asapframework ... which has a class called ActionQueue to which you can add TimedAction items. The great thing about TimedAction & ActionQueue is the feature to add an undo method and arguments, if you need to run the sequence backwards.
Using sequencers is a lot simpler than setting up a mass of timers manually.
i don't really understand your question. actionscript is synchronous in general (except for some AIR functions that can be executed asynchronously), but a timer is asynchronous in the sense that your code will not pause and wait for the timer to complete before continuing the main thread.
if you want your methods to only execute following the completion of a timer, use the timer event TIMER_COMPLETE event listener.

Action Script Sleep function [duplicate]

This question already has answers here:
actionscript 3 sleep?
(2 answers)
Closed 10 years ago.
Does actionscript 2.0/3.0 have an equivalent of c# sleep() ?
Not really. You could block (almost all) code execution with something like:
function sleep(ms:int):void {
var init:int = getTimer();
while(true) {
if(getTimer() - init >= ms) {
break;
}
}
}
trace("hello");
trace(getTimer());
sleep(5000);
trace("bye");
trace(getTimer());
But I don't see how could this be useful in flash. And, at the same time, anything like the above code is a very bad idea as the player will freeze and become unresponsive (and could also give a script timeout if you exceed the timeout limit, which is 15 by default).
If you merely want to delay the execution of a piece of code, you can use a Timer object or the setTimeout function. This will be non-blocking, though, so you'll have to use some kind of flag like TandemAdam suggested. It'll be brittle, at best.
Maybe there's a better approach for your problem, but it's not clear what are you trying to accomplish in your question.
You can implement a sleep function like this:
function sleep(counter: int, subsequentFunction: Function, args: Array): void
{
if (counter > 0)
callLater(sleep, [counter - 1, subsequentFunction, args]);
else
callLater(subsequentFunction, args);
}
Call it with the function which should be processed after the pause.
// call trace('Hello') after 100 cycles
sleep(100, trace, ['Hello']);
// call myFunction() after 50 cycles
sleep(50, myFunction, []);
The advantage of this approach is that the UI is still responsive during the sleep.
No ActionScript/Flash Player does not have an equivalent to the c# sleep function. For one thing Flash does not use multiple Threads.
You would have to implement the functionality manually.
You could use a Boolean flag, that your code would only execute when true. Then use the Timer class, for the delay.