JGC
JGC

Reputation: 12997

Put a Delay in Javascript

I need to add a delay of about 100 miliseconds to my Javascript code but I don't want to use the setTimeout function of the window object and I don't want to use a busy loop. Does anyone have any suggestions?

Upvotes: 96

Views: 414031

Answers (7)

Todor Vasilev
Todor Vasilev

Reputation: 1

Solution for Google Apps Script users:

I couldn't get the setTimeout() function to work with Google Apps Script (just keep getting the error that the function is not defined) so I had to do something like this using the getTime() function and creating a reference time object and then an infinite loop that creates a separate time object every time it loops and checks if the value is greater than the reference time + the delay we need. I guess this way of doing it is not that precise down to the millisecond because there is looping and computational power/lag involved but for an approximate delay for something that is not a big deal weather 1 second is actually 1.013 or similar it will work.

const delay = 3000 // in ms
const date = new Date();
let time = date.getTime() + delay;
console.log('Start before delay.')
// Any code before the delay here
while(1){
    const date2 = new Date(); // diffetent date object for comparison
    let breaker = date2.getTime();
    if (breaker>time){
        console.log('Delayed message.')
        break;
    }
}
// Code after the delay here

Upvotes: 0

Nicholas Blasgen
Nicholas Blasgen

Reputation: 872

If you're okay with ES2017, await is good:

const DEF_DELAY = 1000;

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms || DEF_DELAY));
}

await sleep(100);

Note that the await part needs to be in an async function:

//IIAFE (immediately invoked async function expression)
(async()=>{
  //Do some stuff
  await sleep(100);
  //Do some more stuff
})()

Upvotes: 40

Kaushik
Kaushik

Reputation: 1

Use a AJAX function which will call a php page synchronously and then in that page you can put the php usleep() function which will act as a delay.

function delay(t){

var xmlhttp;

if (window.XMLHttpRequest)

{// code for IE7+, Firefox, Chrome, Opera, Safari

xmlhttp=new XMLHttpRequest();

}

else

{// code for IE6, IE5

xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

}

xmlhttp.open("POST","http://www.hklabs.org/files/delay.php?time="+t,false);

//This will call the page named delay.php and the response will be sent to a division with ID as "response"

xmlhttp.send();

document.getElementById("response").innerHTML=xmlhttp.responseText;

}

http://www.hklabs.org/articles/put-delay-in-javascript

Upvotes: -13

user2390733
user2390733

Reputation: 509

I just had an issue where I needed to solve this properly.

Via Ajax, a script gets X (0-10) messages. What I wanted to do: Add one message to the DOM every 10 Seconds.

the code I ended up with:

$.each(messages, function(idx, el){
  window.setTimeout(function(){
    doSomething(el);
  },Math.floor(idx+1)*10000);
});

Basically, think of the timeouts as a "timeline" of your script.

This is what we WANT to code:

DoSomething();
WaitAndDoNothing(5000);
DoSomethingOther();
WaitAndDoNothing(5000);
DoEvenMore();

This is HOW WE NEED TO TELL IT TO THE JAVASCRIPT:

At Runtime 0    : DoSomething();
At Runtime 5000 : DoSomethingOther();
At Runtime 10000: DoEvenMore();

Hope this helps.

Upvotes: 17

stoimen
stoimen

Reputation: 564

Actually only setTimeout is fine for that job and normally you cannot set exact delays with non determined methods as busy loops.

Upvotes: 4

Andrew Moore
Andrew Moore

Reputation: 95434

Unfortunately, setTimeout() is the only reliable way (not the only way, but the only reliable way) to pause the execution of the script without blocking the UI.

It's not that hard to use actually, instead of writing this:

var x = 1;

// Place mysterious code that blocks the thread for 100 ms.

x = x * 3 + 2;
var y = x / 2;

you use setTimeout() to rewrite it this way:

var x = 1;
var y = null; // To keep under proper scope

setTimeout(function() {
    x = x * 3 + 2;
    y = x / 2;
}, 100);

I understand that using setTimeout() involves more thought than a desirable sleep() function, but unfortunately the later doesn't exist. Many workarounds are there to try to implement such functions. Some using busy loops:

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

others using an XMLHttpRequest tied with a server script that sleeps for a amount of time before returning a result.

Unfortunately, those are workarounds and are likely to cause other problems (such as freezing browsers). It is recommended to simply stick with the recommended way, which is setTimeout()).

Upvotes: 155

Alex Martelli
Alex Martelli

Reputation: 882631

This thread has a good discussion and a useful solution:

function pause( iMilliseconds )
{
    var sDialogScript = 'window.setTimeout( function () { window.close(); }, ' + iMilliseconds + ');';
    window.showModalDialog('javascript:document.writeln ("<script>' + sDialogScript + '<' + '/script>")');
}

Unfortunately it appears that this doesn't work in some versions of IE, but the thread has many other worthy proposals if that proves to be a problem for you.

Upvotes: 3

Related Questions