setTimeout, setInterval, or onEnterFrame?

When time is an issue, which method will you stick with? A recent article I read called Programming with Timers: Don’t be fooled had me thinking hard about my next project.

onEnterFrame fires at a variable time interval depending on each computer’s processor and previous code execution, but even though setInterval and setTimeout fire every x milliseconds, they still aren’t very accurate because their restart time begins when their last script has ended ( which can be milliseconds off ). Assuming you loop every 1000 milliseconds, you may end a loop 30-80 milliseconds off target, restarting the loop at that point with possible another 30-80 milliseconds off will put you 60-160 milliseconds over in 2 seconds.

Timer Class
Not covered is the Actionscript 3.0 version, read up about it here.

setInterval
setInterval fires a function every x milliseconds. You have to use clearInterval ( intervalId ) to stop a loop. Typically there are scope issues that could be solved using the Delegate class.

var intervalId = setInterval ( this,executeCallback, duration );
clearInterval ( intervalId );

setTimeout
setTimeout is just like the setInterval function except it only runs ONCE! This is great for tool-tips, rollOuts, and any non-looping event.

var intervalId = _global [ setTimeout]( this,executeCallback, duration );
_global [clearTimeout] ( intervalId );

onEnterFrame
onEnterFrame is a MovieClip event that occurs every frame. By default the onEnterFrame is undefined for a new MovieClip but you can overload the MovieClip onEnterFrame with a new function.

// Overloading
var mc = this.createEmptyMovieClip ( ‘mc’, this.getNextHighestDepth());
mc.onEnterFrame = function() { trace( this ) };

OnEnterFrameBeacon
If you prefer, subscribe to the MovieClip Class OnEnterFrameBeacon Event. According to Darron Schall, onEnterFrameBeacon reserves depth 9876 and uses “mx.transitions.BroadcasterMX” to broadcast the “onEnterFrame” message instead of AsBroadcaster.

// Listener
mx.transitions.OnEnterFrameBeacon.init();
var obj:Object = {};
Mouse.addListener(obj);
obj.onMouseDown = function()
{
MovieClip.addListener( this );
}
obj.onMouseUp = function()
{
MovieClip.removeListener( this );
}
obj.onEnterFrame = function() { trace( ‘mouseDown’ ); };

»     » del.icio.us     » Digg It!

Tags: , , , , , , ,

5 Comments »

  1. Michael said,

    December 2, 2006 @ 9:00 pm

    One important thing to note is that timers always work to execute as close to their target interval as possible. Even though a timer can be off, it is still working to be close. Dealing with frame events on the other hand is a different story.

    The decision to draw data to the screen is made on an application wide level, careful consideration is taken by the developers to ensure that drawing their data doesn’t intrude on the end user in any way. Therefore events tied to drawing the screen are inherently subject to the same considerations. This means that your frame event reliant code is optimized such that if it were to break, the end users compuer is not affected, and by ‘not affected’ I mean there is usually some kind of graceful degradation.

    I unfortunately have limited resources in knowing the exact inner workings of the Flash Player, so all information is based on my understanding of virtual machines in general.

    With that said, there is nothing to say that timers are not affected by the VM in the same way that frame events are. However through what I have tested it does not seem so. It seems that timers are executed on a more direct level than frame events. This means that a lack of consideration in this aspect can leave your application in ruins.

    The use of timers and updateAfterEvent() can lead to serious issues within your application. If a timer is set to some unreasonably low value the operating system can only go so far as to accomodate the Flash Player. This means that it’s not likely that your actual interval will reflect your desired interval. The reason this happens can be any of an infinite possibilities. Most likely though, it is caused by your computer not being capable of processing all of its running applications. The developer must remember that no matter how crafty they are, they’re still bound by the same physical laws the rest of the universe is. It will always become more difficult, the more data you have to process.

    The reason that your flash application begins to run slowly has just as much to do with how it is designed as it does with how the computer it’s running on executes it. In short, use what the developers give you, don’t try to force an application to do something it’s already having a hard time doing. This leaves the issue of timers and frame events up as a design consideration for you the developer.

    Both intervals/timers and frame based events are completely acceptable solutions to any problem that has planned their use in an ‘efficieny’ aware manner.

    Sorry, don’t know what that was about… :) Great blog, keep up the good work.
    Michael

  2. jgraup said,

    December 6, 2006 @ 8:09 pm

    Check back:
    http://stimpson.flashvacuum.net/mt/archives/2006/08/as_30_framedela.html

  3. jgraup said,

    March 2, 2007 @ 5:05 pm

    comment >>

    You can prevent the compiler from showing errors by adding the following line:

    intrinsic function setTimeout():Number;

    to your toplevel.as file, located in
    “documents and settings\\Local Settings\Application Data\Macromedia\Flash 8\en\Configuration\Classes” folder.

    Conversely, for MTASC, you can add the following line:

    static function setTimeout():Number;

    to the TopLevel.as, located in MTASC’s “std” folder.

  4. jgraup said,

    April 24, 2007 @ 4:16 pm

    function clearAllIntervals ( )
    {
    // create new interval
    var id = setInterval ( this, ‘blank’, 0 );
    while ( id != 0 ){
    // count through all interval and clear them one by one
    clearInterval ( id )
    id–
    }
    }
    clearAllIntervals ( );

  5. jgraup said,

    April 24, 2007 @ 4:45 pm

    Testing the theory..

    //
    // FRAME / INTERVAL
    //

    fTime = getTimer()
    iTime = getTimer();
    var frame = 0;

    var id = setInterval ( this, ‘onInterval’, 0 );
    function onInterval () {
    var now = getTimer();
    var change = now - iTime;
    iTime = now;
    trace( ‘onInterval: \tf: ‘ + ( frame ) + ‘\tc: ‘ + change );
    }

    this.onEnterFrame = onFrame;
    function onFrame()
    {
    var now = getTimer();
    var change = now - fTime;
    fTime = now
    trace( ‘\nonFrame: \tf: ‘ + ( frame++ ) + ‘\tc: ‘ + change + newline);
    }

    onFrame: f: 93 c: 88

    onInterval: f: 94 c: 8
    onInterval: f: 94 c: 8
    onInterval: f: 94 c: 8
    onInterval: f: 94 c: 8
    onInterval: f: 94 c: 8
    onInterval: f: 94 c: 8
    onInterval: f: 94 c: 8
    onInterval: f: 94 c: 8
    onInterval: f: 94 c: 26

    onFrame: f: 94 c: 90

    onInterval: f: 95 c: 73
    onInterval: f: 95 c: 5
    onInterval: f: 95 c: 8

    onFrame: f: 95 c: 86

    onInterval: f: 96 c: 8
    onInterval: f: 96 c: 8
    onInterval: f: 96 c: 8
    onInterval: f: 96 c: 8
    onInterval: f: 96 c: 8
    onInterval: f: 96 c: 8
    onInterval: f: 96 c: 8
    onInterval: f: 96 c: 8
    onInterval: f: 96 c: 8
    onInterval: f: 96 c: 8
    onInterval: f: 96 c: 8

RSS feed for comments on this post · TrackBack URI

Leave a Comment

You must be logged in to post a comment.

best kansas city bookstore pirodr! 666