doLater vs setInterval

Here’s a brief explanation of how you can delay the execution of a function and why you would want to do that.

Most programming languages have a way for you to execute code after a delay. These are timer functions – you set a delay and after that time period expires the code you specify executes. Java for example, has the Thread.sleep() method.

ActionScript is no different. If you want to make a clock for example, you’d like to have the second hand move every, well, second. Since the computer is capable of executing hundreds of instructions per second, you need to set a timer so that the code to position the hands of clock executes every second or 1,000 milliseconds.


setInterval

setInterval( obj:Object, fn:String, delay:Number [,arg1, arg2, ...] ) : Number

The setInterval method has three required parameters:

obj: This is the object in whose context the function is found. Often this is used.
fn: This is the name of the function defined on obj which is executed every delay milliseconds.
delay: This the amount of time between executions of the function.

You can also pass extra arguments to setInterval if the fn function requires them.

setInterval returns a unique Number identify the interval created.

Keep in mind that the function is executed repeatedly until told to stop using clearInterval:

clearInterval( intervalID:Number ) : Void

Pass the value returned by setInterval to clearInterval.

doLater

Unlike traditional programming languages, ActionScript is executed within the Flash Player. If you are at all familiar with Flash, you know that Flash is based on the movie concept of a timeline. You place your symbols and code in various frames. The Flash movies are run at specified frame rates. Flex movies are executed at 24 fps.

What you may not know, is that Flash updates the visuals (color, object placement, size, etc.) at the end of the frame. This gives the ActionScript in the frame a chance to execute and set up the visual changes. For instance, if you use ActionScript to change a line from blue, to black, to red within the code for a single frame, you will see only a red line. That’s because each change the line’s color is not changing the visual aspect of the line – it is merely changing the line’s property. So changing the property from blue to black to red is overwriting the property. When the frame code has finished, Flash updates the visual aspect of the line to last value of the property – red in this case.

So what does this have to do with doLater? Everything. The doLater method allows you to execute code once the UI has been updated.

The doLater method is defined for the Flex mx.core.UIObject, so any class that extends a control, container, or chart can use doLater.

When to use doLater

It is not always obvious when to use doLater. Typically, if you try to do something and the UI has not updated, put the last thing you want to do into a doLater method.

For example: suppose you want to change the dataProvider for a List and then have the list positioned to show a particular item in the new list. You might try this first:

myList.dataProvider = new_data;
myList.vPosition = 45;

A couple of things could have: it could work as you expect (unlikely) or the new data will appear, but the list will not be positioned correctly (most likely).

When you change the dataProvider for a list, the UI is normally updated at the end of the frame in which the dataProvider was assigned. Since the instruction to change the position of the list will have happened before the UI changed, position 45 may not exist (or may not yield the correct location once the data has been formatted for the display).

You make this work properly by putting the change to vPosition in a doLater method:

function scrollLater() {
myList.vPosition = 45;
}

Now write the code to change the dataProvider and scroll the list:

myList.dataProvider = new_data;
doLater( this, "scrollLater" );

The doLater method’s signature is similar to that of setInterval:

doLater( obj:Object, fn:String [,args:Array] ) : Void

obj: This is the object on which the function is to operate. The object is often this.
fn: This is the name of the function defined on obj.
args: This is an optional Array of arguments. For example: [“cats”,345]. The function itself would be defined to take two arguments: fn( animal:String, quantity:Number ).

doLater has several important differences with setInterval:

  • The doLater function executes once; the setInterval function executes repeatedly until cleared.
  • The doLater function executes at the end of the current frame; the setInterval function executes after a specified delay.
  • The doLater function does not return any arguments; the setInterval function returns an interval ID.

An example of using doLater can be found in this blog under the Ticker
application. I use doLater to move text across the screen.

Summary

Use doLater if you do not need to specify an exact delay for the task and you need to do something once. Use setInterval if you want to repeatedly do something or if you want to delay task for a specific amount of time.

11 Responses to doLater vs setInterval

  1. JesterXL says:

    Just to compliment this much needed blog entry, this WILL run the function twice, on the same frame:

    doLater(this, “foo”);
    doLater(this, “foo”);

    The function “foo” will run twice.

    Also, your list example is a great example. For those making components, doLater is great for those times where you yourself are changing data in your component. Let’s take a label:

    private var _label:String = “”;

    public function set label(str:String):Void
    {
    _label = str;
    doLater(this, “updateLabel”);
    }

    private function updateLabel():Void
    {
    label_lbl.text = _label;
    }

    Why doLater? What if you had:

    yourComponent.label = “moo”;
    yourComponent.label = “123”;
    yourComponent.label = “sup g”;

    Perhaps this is set in a loop, or you are updating a player’s score. This ensures that the text will only update the label once per frame since that is the only time Flash can update the screen anyway.

    Great post Peter!

  2. Sven Busse says:

    hello,

    doLater is not a native Flash function, right? I tried this little example on the main timeline and nothing happens:

    _root.doit = function() {
    trace(“doit called.”);
    }
    doLater(_root, “doit”);

    Might be usefull to mention, as setInterval is a native function, i believe.

  3. Peter Ent says:

    Thanks for comments. I added a short note to the entry that explains that doLater is a method on mx.core.UIObject. I hope that clears up the confusion.

  4. pim says:

    Let’s say you have 10 records to display onscreen and you want them to appear one by one.
    If you use the following code:
    for(var a = 0; a < 10; a++){
    _level0.attachMovie …
    }
    they all appear together at the end of the loop, so in flash we must use a setInterval to achieve this.
    In flex, could you use doLater() in a for loop and have the Stage refreshed ?
    like this:
    for(var a = 0; a < 10; a++){
    doLater(_level0, “attachMyMovie”) …
    }
    Regards

  5. Peter Ent says:

    Using doLater would not really help. All that would do is schedule the attachMovies at the end of the current frame and I would think you would see them all together. What you would want to do have your attachMyMovie attach the first movie, then call doLater again and so forth until all of the movies were attached.

  6. pim says:

    Ok that would be the same as using the setInterval way, except that you are dependant of the flash movie frameRate (12 fps) that you can’t change in Flex, can you?

  7. chris says:

    I have a simple follow-up question…

    I have a Flash movie with many layers and i want some control over the time a layer displays, separate from the timeline and frames per second. Is there a function I can drop into a frame that lets me control it’s display time in seconds and then continue playing the movie? Like a delay or setTimeOut() in javscript.

    My current approach, simply adding many frames to a layer to extend display time, seems like extra work, is inefficient, and effects file size.

    All help appreciated.

    Chris

  8. Stepan says:

    I’ve tried to use doLater to change vPosition (scroll to first selected item) of a List, just like in the example with one exception- the list has some 220 rows, it gets enabled & heap of other UI is supposed to get populated at the same time.
    doLater didn’t work – finally managed to make it scroll using setInterval with delay=600. Delay 500 or lower doesn’t work.
    That’s kind of dodgy ’cause I suppose it may not work on slower computer (than) mine; or, if I make the Delay say 3000ms, it won’t show fast enough…

    Any ideas? I can’t think of an event I could tie this to… something like componentIsREALLYPopulatedEvent…

    I think that in case it takes several frames to updateUI (which seems to be happening), doLater should occur after it’s owner has applied all changes.

    OH yeah, this is happening in Flex 1.5, happy to send the mxml on request (and thanks beforehand)…

  9. Parag says:

    Using setInterval() we can acess private varaibles?
    Means
    class
    {


    ..
    setInterval(abc,0,”Hi”)
    private abc()
    {
    trace(“Hi”)
    //here can i use privte variables of class
    }



    }

  10. Raz Gilad says:

    Hi Peter

    I have a similar issue that I’m unable to resolve – while the doLater command delay a certain function till the end of the frame , is there a way – in Flex – to delay the current code and provide other threads to complte – for example is it possible that a certain code will open a window and will wait until this window will be closed?

    Thanks

    Raz Gilad

  11. Peter Ent says:

    There are no threads in the Flash Player/ActionScript. So there is no way to do what you want in a thread-manner.

    Please check Alex Harui’s blog for some thread alternative ideas:
    http://blogs.adobe.com/aharui/2008/01/threads_in_actionscript_3.html

    –peter