faqts : Computers : Programming : Languages : JavaScript

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

1030 of 1162 people (89%) answered Yes
Recently 8 of 10 people (80%) answered Yes

Entry

How do I pause execution in JavaScript?
How do I pause execution in JavaScript?
Is there a wait statement in JavaScript?
Is there a sleep method to pause execution?
Is there a sleep method to pause execution?
setTimeout does not work well when called recursively in NN 6.0. Works fine with IE 5.0 and above

Apr 4th, 2008 21:19
ha mo, Daniel LaLiberte, Brent Boyer, Martin Honnen, mercury rising,


There is no true wait, sleep, or similar function in either the core
JavaScript language or in client side JavaScript.
Client side JavaScript however provides
    setTimeout('js code here', delayInMilliseconds)
which allows you to schedule execution of piece of script and
    setInterval('js code here', intervalInMilliseconds)
which allows you to periodically excute a piece of script.
So if you wanted (pseudo code)
    statement1;
    wait (someDelay);
    statement2;
you would stuff the code into functions 
    function statement1 () {
        // your code here
    }
    function statement2 () {
        // your code here
    }
and call
    statement1();
    setTimeout('statement2()', someDelay);
If you wanted (pseudo code)
    while (someCondition) {
        statement1;
        wait (someDelay)
    }
you code
    var tid;
    function statement1 () {
        // your code here
        if (!condition)
            clearInterval(tid);
    }
    tid = setInterval('statement1()', someDelay);
Note that both setInterval and setTimeout return a timer id you can use
to clear the scheduled execution e.g.
    var tid = setTimeout('js code here', delayInMilliseconds);
    ...
    clearTimeout(tid);
respectively
    var tid = setInterval('js code here', delayInMilliseconds);
    ...
    clearInterval(tid);
There are some major limitations with the solution given above.  First,
it makes your code more awkward to write and difficult to read.  Even
worse, the above technique will not work at all for certain situations.
For instance, consider a function that has state (i.e. local variables):
it may be impossible to split it apart into 2 functions as called for
above, since each half may need access to the full state.  (It may be
impossible to store the state in global variables instead of locals
--say,  if you are using the function recursively.  Also, you cannot
pass the state as args to the second function via setTimeout/setInterval
because those functions only take Strings as the function 
specification.)
Below is a Javascript function that (from the callers perspective) is in
fact a true pause:
    /*
    * This function will not return until (at least)
    * the specified number of milliseconds have passed.
    * It does a busy-wait loop.
    */
    function pause(numberMillis) {
        var now = new Date();
        var exitTime = now.getTime() + numberMillis;
        while (true) {
            now = new Date();
            if (now.getTime() > exitTime)
                return;
        }
    }
The main problem with this function is that it is not sleeping the
underlying Javascript interpreter thread.  Instead, it is worthlessly
burning up a lot of CPU cycles.  If you have a modern multithreaded
browser, other processes (e.g. loading of a webpage) should still take
place in other threads, but they will not finish as fast as they ought.
A sneaky way to get the effect of a true pause while not
burning CPU cycles is to use a modal dialog with a timeout that closes
the modal dialog window and resumes execution.  A modal dialog pauses
execution in the code that created it, but allows other threads to
continue. 
    /*
    * This function will not return until (at least)
    * the specified number of milliseconds have passed.
    * It uses a modal dialog.
    */
     function pause(numberMillis) {
        var dialogScript = 
           'window.setTimeout(' +
           ' function () { window.close(); }, ' + numberMillis + ');';
        var result = 
// For IE5.
         window.showModalDialog(
           'javascript:document.writeln(' +
            '"<script>' + dialogScript + '<' + '/script>")');
/* For NN6, but it requires a trusted script.
         openDialog(
           'javascript:document.writeln(' +
            '"<script>' + dialogScript + '<' + '/script>"',
           'pauseDialog', 'modal=1,width=10,height=10');
 */
     }
If you want a true and CPU efficient pause, you will need to use a real
language.  Your best choice is Java.
Client side JavaScript in NN4+ has direct access to Java objects via
NN's LiveConnect technology, so your Javascript can simply call
    java.lang.Thread.sleep(timeInMilliSeconds)
CAUTION: if the JVM (Java Virtual Machine) has not yet started, there is
an additional (several second) JVM start delay before your sleep call is
executed.  Subsequent calls will then delay the correct amount.
Officially, IE does not support Liveconnect.  So, if you want a reliable
cross browser solution, you can simply embed the above in a public
method of a Java applet as follows:
    /**
    * Simply calls <code>Thread.sleep( (long) timeInMillis )</code>.
    * <p>
    * This method is needed because Javascript has no sleep
    * functionality. Also, the argument must be a float
    * because that is what Javascript's Number type is
    * automaticly converted to when it calls this method.
    * <p>
    * @see <a
href="http://home.netscape.com/eng/mozilla/3.0/handbook/javascript/livec
on.htm#1007805">Data
type conversion</a> 
    */
    public void sleep(float timeInMillis) throws InterruptedException {
        Thread.sleep( (long) timeInMillis );
    }
If the above is a member of the first Java applet in your html file, you
may then invoke it from your Javascript like
    window.document.applets[0].sleep(2*1000);    // sleep for 2 seconds
WARNING: you should verify whether or not the browser you want to work
in is actually intelligently multithreaded (i.e. runs the Javascript
interpreter in it's own thread).  A way that you can simply test this is
to write a very large loop that doesn't do much and see whether or not
the browser can still do things like respond to its GUI.  Using this
technique, it has been reported that NN appears to run the JS
interpreter in the same thread as the browser gui.
http://www.businessian.com
http://www.computerstan.com
http://www.financestan.com
http://www.healthstan.com
http://www.internetstan.com
http://www.moneyenews.com
http://www.technologystan.com
http://www.zobab.com
http://www.healthinhealth.com