« Efficient Component Layout | Main | Using Flex with .NET »

May 16, 2005

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.

Posted by pent at May 16, 2005 02:28 PM

Trackback Pings

TrackBack URL for this entry:
http://weblogs.macromedia.com/mtadmin/mt-tb.cgi/6252

Listed below are links to weblogs that reference doLater vs setInterval:

» hand job from
hand jobs girl squirt masturbating dildos hand job dildo lesbian dildo lesbian [Read More]

Tracked on September 23, 2005 03:29 AM

» prescription drugs without prescription from prescription drugs without prescription
prescription drugs without prescription [Read More]

Tracked on October 27, 2005 02:00 AM

» diet pills from diet pills
diet pills [Read More]

Tracked on October 28, 2005 01:05 AM

» christmas cards from christmas cards
christmas cards [Read More]

Tracked on November 20, 2005 08:34 PM

» Strong Search Engine Action Indicates Resurgence Of Interest In ... from Diet News Blog
If you pick up your local newspaper or watch the news on television, it's almost hard to imagine why anyone would still be on the Atkins or low-carb diet anymore. We have witnessed an unprecedented all-out war on the low-carb lifestyle like nothing els... [Read More]

Tracked on January 16, 2006 08:40 AM

» Carburetor from Carburetor
Also, if the off-season, and dry, or maybe the end of the Holley nut clockwise (CW) to know what tools and put it doesnt come in the choke,... [Read More]

Tracked on February 22, 2006 09:43 AM

» Diet Pill from Diet Pill
Best Diet Pill US & Intl Order It Online, Cheaply & Conveniently HERE ! !Diet Pill survey Resouces, detailed diet reviews, academic ... [Read More]

Tracked on March 21, 2006 08:30 PM

» Diet Pills from Diet Pills
Despite the fact that weight lossslimming web site * association for morbid obesity, diet pills good effects fasting diet pills weight lo... [Read More]

Tracked on April 3, 2006 11:00 AM

Comments

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!

Posted by: JesterXL at May 16, 2005 07:23 PM

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.

Posted by: Sven Busse at May 17, 2005 05:34 AM

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.

Posted by: Peter Ent at May 17, 2005 10:12 AM

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

Posted by: pim at June 1, 2005 10:07 AM

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.

Posted by: Peter Ent at June 1, 2005 10:11 AM

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?

Posted by: pim at June 1, 2005 10:31 AM

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

Posted by: chris at October 16, 2005 09:05 PM

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)...

Posted by: Stepan at January 31, 2006 09:48 PM

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
}
...
...
...
}

Posted by: Parag at September 14, 2006 09:44 AM

Post a comment




Remember Me?