views:

9096

answers:

10
+24  Q: 

Javascript sleep

Is any better way than this function to make a sleep in javascript, or should I just use that function? (taken from here)

function pausecomp(millis)
 {
  var date = new Date();
  var curDate = null;
  do { curDate = new Date(); }
  while(curDate-date < millis);
}

This is not a dupe of http://stackoverflow.com/questions/758688/sleep-in-javascript I want a real sleep in a middle of a function, not a delay for a piece of code;

+19  A: 

For the love of $DEITY please do not make a busy-wait sleep function. setTimeout and setInterval do everything you need.

chaos
I agree. Wouldn't a real "sleep" freeze up the whole javascript engine...
Skurmedel
Well not quite everything: setInterval does a much better impression of polling.
annakata
I sometimes miss a real "sleep", but messing around with setTimeout is still better than actively waiting (like the above while loop). A real sleep function does however not need to freeze the JavaScript engine, but a busy-wait would max out a single CPU core. (And eat up precious battery time of mobile users)
wvdschel
What would that piece of code *not* hold back in the JavaScript engine?
Deniz Dogan
@annakata: Yeah, fair enough. Edited per.
chaos
+5  A: 

You can't do a sleep like that in JavaScript, or, rather, you shouldn't. Running a sleep or a while loop will cause the user's browser to hang until the loop is done.

Use a timer, as specified in the link you referenced.

Andrew Dunkman
+26  A: 

In JavaScript, I rewrite every function so that it can end as soon as possible. You want the browser back in control so it can make your DOM changes.

Every time I've wanted a sleep in the middle of my function, I refactored to use a setTimeout().

Nosredna
this solution doesn't work if you have any state variables. If the function you're trying to sleep has any parameters. For example, how can one do fuction foobar(el){ setTimeout(foobar_cont(el),5000); } ??? I haven't figured that out yet.
David Dombrowsky
By way of closure. `function foobar(el) { setTimeout(function() { foobar_cont(el); }, 5000); }`
chaos
ok, and what if the code is not intended to be used in a webpage?
Eugenio Miró
+2  A: 

First:

Define a function you want to execute like this:

function alertWorld(){
  alert("Hello World");
}

Then schedule its execution with the setTimeout method:

setTimeout(alertWorld,1000)

Note two things

  • the second argument is time in miliseconds
  • as a first argument you have to pass just the name (reference) of the function, without the parenthesis
Pablo Fernandez
A: 

This is really not a good idea, doing something like this would cause the entire page to freeze up while the system waited for your function to return.

Scimon
Javascript is not just for webpages but a complete languaje that might be used with wscript for example. -1 for you
Eugenio Miró
+5  A: 

I agree with the other posters, a busy sleep is just a bad idea.

However, setTimeout does not hold up execution, it executes the next line of the function immediately after the timeout is SET, not after the timeout expires, so that does not accomplish the same task that a sleep would accomplish.

The way to do it is to breakdown your function in to before and after parts.

function doStuff()
{
  //do some things
  setTimeout(continueExecution, 10000) //wait ten seconds before continuing
}

function continueExecution()
{
   //finish doing things after the pause
}

Make sure your function names still accurately describe what each piece is doing (I.E. GatherInputThenWait and CheckInput, rather than funcPart1 and funcPart2)

Edit

This method achieves the purpose of not executing the lines of code you decide until AFTER your timeout, while still returning control back to the client PC to execute whatever else it has queued up.

Further Edit

As pointed out in the comments this will absolutely NOT WORK in a loop. You could do some fancy (ugly) hacking to make it work in a loop, but in general that will just make for disastrous spaghetti code.

Yeah. Where this gets tricky is when you have a loop, or a nested loop even. You have to abandon your for loops and have counters instead.
Nosredna
Touché. I mean, it would still be possible, but ugly and hackish in that case. You could also use some static boolean state variables, but that's also pretty hackish.
Any time I have to do it, I comment heavily. JavaScript is meant to run as an event handler, and the pieces are supposed to execute quickly. Making a computation-intensive RIA in JavaScript is certainly possible, but you have to give a lot of time to the browser or your UI gets sluggish. IE, of course, is the worst.
Nosredna
In the example at the bottom of this blog post, I use variables attached to the function to hold the current progress. http://dreaminginjavascript.wordpress.com/2008/08/02/functions_are_weird/
Nosredna
+1  A: 

If you're using jQuery, someone actually created a "delay" plugin that's nothing more than a wrapper for setTimeout:

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
     setTimeout(func,time);
    });

    return this;
};

You can then just use it in a row of function calls as expected:

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');
Alan
That's not a bad solution. Keeps context and chainability.
Nosredna
+2  A: 

I have searched/googled quite a few webpages on javascript sleep/wait... and there is NO answer if you want javascript to "RUN, DELAY, RUN"... what most people got was either, "RUN, RUN(useless stuff), RUN" or "RUN, RUN + delayed RUN"....

So I ate some burgers and got thinking::: here is a solution that works... but you have to chop up your running codes...::: yes, I know, this is just an easier to read refactoring... still...

//......................................... //example1:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setInterval
var i = 0;

function run() {
    //pieces of codes to run
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i >2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==5){document.getElementById("id1").innerHTML= "<p>all code segment finished running</p>"; clearInterval(t); } //end interval, stops run
    i++; //segment of code finished running, next...
}

run();
t=setInterval("run()",1000);

</script>
</body>
</html>

//.................................... //example2:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function run() {
    //pieces of codes to run, can use switch statement
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(1000);}
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(2000);}
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(3000);}
    if (i==3){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>";} //stops automatically
    i++;
}

function sleep(dur) {t=setTimeout("run()",dur);} //starts flow control again after dur

run(); //starts
</script>
</body>
</html>

//................. example3:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function flow() {
    run(i);
    i++; //code segment finished running, increment i; can put elsewhere
    sleep(1000);
    if (i==5) {clearTimeout(t);} //stops flow, must be after sleep()
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow
</script>
</body>
</html>

//.............. example4:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout, switch
var i = 0;

function flow() {
    switch(i)
    {
     case 0:
      run(i);
      sleep(1000);
      break;
     case 1:
      run(i);
      sleep(2000);
      break;
     case 5:
      run(i);
      clearTimeout(t); //stops flow
      break;
     default:
      run(i);
      sleep(3000);
      break;
    }
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    i++; //current segment of code finished running, next...
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow control for first time...
</script>
</body>
</html>
A: 

For the specific case of wanting to space out a set of calls being executed by a loop, you can use something like the code below with prototype. Without prototype, you can substitute the delay function with setTimeout.

function itemHandler(item)
{
    alert(item);
}

var itemSet = ['a','b','c'];

// Each call to itemHandler will execute
// 1 second apart
for(var i=0; i<itemSet.length; i++)
{
    var secondsUntilExecution = i;
    itemHandler.delay(secondsUntilExecution, item)
}
beauSD
A: 

One scenario where you might want a sleep() function rather than using setTimeout() is if you have a function responding to a user click that will ultimately end up opening a new i.e. popup window and you have initiated some processing that requires a short period to complete before the popup is displayed. Moving the open window into a closure means that it typically gets blocked by the browser.

acuth