Using the Timer class in ActionScript 3.0
Another great new addition in ActionScript 3.0 is the Timer class (flash.utils.Timer), which essentially replaces the setInterval() and setTimeout() methods in ActionScript 2.0. For example, here's an example of the setTimeout() method in ActionScript 2.0:
// AS2
var intID:Number = setTimeout(runOnce, 1000); // 1 second
function runOnce():Void {
trace("runOnce() called @ " + getTimer() + " ms");
}
In ActionScript 3.0, the same code could be rewritten as follows:
// AS3
var myTimer:Timer = new Timer(1000, 1); // 1 second
myTimer.addEventListener(TimerEvent.TIMER, runOnce);
myTimer.start();
function runOnce(event:TimerEvent):void {
trace("runOnce() called @ " + getTimer() + " ms");
}
Note that the Timer() constructor takes two parameters. The first parameter controls how frequently the TimerEvent.TIMER event gets dispatched (in milliseconds). The second parameter is the number of times that the TimerEvent.TIMER event will be dispatched before stopping. In this example, the timer will dispatch only once before quitting. If you set the second parameter to 0 (zero) or omitted it completely, the timer would run forever (or until you called the stop() method on the timer instance.
If you wanted the code to continuously run in ActionScript 2.0, you would use the setInterval() method instead of the setTimeout() method, as seen in the following example:
// AS2
var intID:Number = setInterval(runMany, 1000); // 1 second
function runMany():Void {
trace("runMany() called @ " + getTimer() + " ms");
}
The previous code snippet would continue to run until the interval was stopped by calling the clearInterval() method and passing in the interval id (which was saved in the variable intID). The same code could be rewritten in ActionScript 3.0 as follows:
// AS3
var myTimer:Timer = new Timer(1000); // 1 second
myTimer.addEventListener(TimerEvent.TIMER, runMany);
myTimer.start();
function runMany(event:TimerEvent):void {
trace("runMany() called @ " + getTimer() + " ms");
}
Comments
An interesting read! AS3 really seems to add some useful features to the platform.
Keep the articles coming! :)
Posted by: Mike | July 5, 2006 07:58 PM
is the timer class still frame dependent?
i find setinterval to be too inaccurate in many instances.
thank you
Posted by: sean | October 18, 2006 02:12 AM
Very cool.
Nice article.
Posted by: Ivan | October 23, 2006 01:47 PM
hi peter,
nice ....
but how to stop or clear...timer
http://sara-intop.blogspot.com
Posted by: saravanan | September 12, 2007 03:52 AM
saravanan,
You can stop the timer by calling its stop() method.
For example:
var myTimer:Timer = new Timer(1000); // 1 second
myTimer.addEventListener(TimerEvent.TIMER, runMany);
myTimer.start();
You could stop the timer at any point by using:
myTimer.stop();
For more information on the Timer class, check out the Flash CS3 LiveDocs at http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/Timer.html
Thanks,
Peter
Posted by: Peter | September 12, 2007 09:31 AM
Hi, I find that you cant pause the timer a major lack of an important feature.
- MaTT
Posted by: matthew | October 8, 2007 09:45 AM
MaTT,
While there is no "pause()" method in the timer class, there is a stop() and start() method. Note that calling the stop() method stops the current timer, but does not reset the count timer, so you can call start() and resume from your existing repeat count. Although, if you do want to stop the counter and reset the repeat count, there is a reset() method.
So it sounds like stop() may do what you want.
Peter
Posted by: Peter | October 8, 2007 09:53 AM
Oh, so if you have a timer set to 8000 ms and call stop at 4000 and then start again, it will start from 4000 and run to 8000? I have it set to inifinte as the repeatCount is 0?
Thanks
Posted by: matt | October 8, 2007 10:06 AM
MaTT,
Ah, I see what you're saying.
No, I'm pretty sure that if you call the stop() and then start() methods, you'll reset the timer. So if you have a timer set to 8000 ms and call stop() at 4000 and then start again, it will start from 0 (not 4000) and run to 8000.
In fact, here's a quick little test I made in Flex (note that i changed my interval to 4000 cause i got tired of waiting 8 seconds for each update):
Posted by: Peter | October 8, 2007 10:37 AM
Hi Peter, I also did a test. So basically, there is no real pause. Hence it's not a true timer class if you cant pause the timer, correct? Thing is I'm using this to set an interval on some video playback. Problem is, if the user pauses the video, one can clear the interval, but then when you restart, it fires at the wrong time. I guess I can use a smaller interval and increment a counter as a hack to eliminate massive errors. Adobe should look into a true timer implementation as the help docs say you should rather user Timer than interval.
cheers
MaTT
Posted by: matt | October 8, 2007 11:04 AM
MaTT,
If you want to pass that along the enhancement request to the Flash Player team, the best way to do that is probably using the Wishlist form at http://www.adobe.com/go/wish?product=17
(just make sure you mark it as Flash Player and give as much detail as you can)
Peter
Posted by: Peter | October 8, 2007 11:12 AM
Is it possible to recall time from the timer class? I want to use it like a stop watch and then have it display the amount of time that the timer was active.
Posted by: some_guy | October 25, 2007 04:21 PM
There is a getTimer() method in the flash.utils package, although that tracks the amount of time since the Flash Player has been initialized. See http://livedocs.adobe.com/flex/201/langref/flash/utils/package.html#getTimer().
If you want to use the Timer class, I'd just create a temporary variable that holds the time when the timer was initialized, and then do some subtraction from the current date. Something like this in Flex:
<mx:Script>
<![CDATA[
private var start:Date;
private var timer:Timer;
private function init():void {
start = new Date();
timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, updateTimer);
timer.start();
}
private function updateTimer(evt:TimerEvent):void {
var now:Date = new Date();
var diff:Date = new Date(now.time - start.time);
lbl.text = ">>" + dateFormatter.format(diff);
}
]]>
</mx:Script>
<mx:DateFormatter id="dateFormatter" formatString="NN:SS" />
<mx:Label id="lbl" creationComplete="init();" />
</mx:Application>
HTH,
Peter
Posted by: Peter | October 25, 2007 04:38 PM
Which way produces more consistent times? The application I am creating will be used for research purposes and involves measuring reaction times. I have to keep the errors to a minimum.
Thanks for your help!
Posted by: some_guy | October 26, 2007 07:12 AM
I haven't done any tests to try and determine which is more reliable. It really depends on your specific use case as to which is easier to do.
You cant pause/stop the getTimer() timer. It simply starts counting as soon as the SWF is loaded/initialized. It should be pretty easy to determine reaction times by storing the current value of getTimer() when some event happens, and then get the value again when event 2 happens. Subtract the second getTimer() value from the first, and that should give you a pretty good measure of the number of milliseconds between the two events.
Although, if you're trying to force an action in under X seconds, you may want to use a Timer. This lets you say "if action X hasnt been finished in Y milliseconds, do Z".
Just remember that Flash Player isn't real time. Just because you set a timer for 1000 ms, doesn't mean it will execute exactly every 1000 ms. It may execute at 1000 or 1100 or anywhere in between.
Hope that helps,
Peter
Hope that helps.
Posted by: Peter | October 26, 2007 10:16 AM
it would be easy to build a pause event
just extend the timer class and make pause method which will keep track of start time and pause time and calculate the rest
only problem would be first time it continues but it's not a problem just two or three lines more
Posted by: MrSteel | January 16, 2008 09:47 AM
This was exactly what I needed and it worked great. Thanks!
Posted by: tunghoy | January 19, 2008 01:54 PM
Here i have to design a media player in flex exactly same as windows media player .i m buiding up basic things like play pause stop they are working .. but problem is with volume control n slider bar . slider control i have to build for forwarding or reversing d video
Posted by: Amruta | February 20, 2008 12:15 AM
Hi Peter,
What I find frustrating is that the handler method always expects a TimerEvent. What if I just want to call a function that expects an object 'foo' after a certain time? There doesn't seem to be a way to achieve this in AS3, whereas in AS2 the setInterval method van handle this without a problem.
Posted by: Sander | February 29, 2008 09:33 AM
Sander,
Good question, actually, I just blogged a couple of potential solutions/workarounds on my other blog about a week ago. For more information, check out "Creating custom timers by extending the Timer class" on flexexamples.com.
Basically I came up with two custom solutions, a DataTimer class which lets you specify a "data" parameter on a Timer instance, and a DynamicTimer class which lets you add any additional methods/properties you want to the Timer object.
The ActionScript classes (DataTimer.as and DynamicTimer.as) should be usable in Flash or Flex, but the rest of the code on the page is for Adobe Flex.
Peter
Posted by: peterd | February 29, 2008 09:44 AM
Hi Peter,
Thanks for the swift reply. Both approaches will come in handy.
Pretty good stuff on your other site too!
Posted by: Sander | March 3, 2008 12:47 AM
Hi, hopefully someone can answer this. I'm not a programmer but the above seems to be on the right track of what I'm looking for.
In AS 3.0, I just want some simple reusable code I can put on a frame to stop the timeline for a given number of milliseconds, then after the time I set is complete, go to a frame label.
Anyone?
Posted by: Surly | April 30, 2008 12:41 PM
How do I synchronize two timers ?
For example a custom object has two timers and each handler is changing a class variable... how do I make sure that each one waits till the other one is done.
This is a simple example. now extrapolate to fifty timers objects...
Drop me an email if have a good answer...
Q
Posted by: theqmaster | May 21, 2008 04:48 PM
Hi Peter,
I am working on a timer inside a timer. For some reason I keep getting error's. Do you know if it is posible to have a timer inside a timer?
(after 3 seconds give a new question and after 6 seconds give the answer to the new question)
Thank You!
Annelies
Posted by: Annelies | May 27, 2008 03:01 PM